Ce document est une traduction de la recommandation XML Schema du W3C, datée du 2 mai 2001. Cette version traduite peut contenir des erreurs absentes de l'original, introduites par la traduction elle-même. La version originale en anglais, seule normative, se trouve à l'adresse http://www.w3.org/TR/2001/REC-xmlschema-0-20010502/. Traduction :
Copyright © 1998 W3C (MIT, INRIA, Keio), tous droits réservés. Les règles du W3C sur la responsabilité, les marques commerciales, les droits des auteurs et les licences des logiciels sont applicables. Remarque de la traduction: L'entité caractère nécessaire au "oe" ligaturé n'étant pas supportée par certains navigateurs, ce caractère sera écrit oe. |
Copyright ©2001 W3C® (MIT, INRIA, Keio), All Rights Reserved. W3C liability, trademark, document use et software licensing rules apply.
Le tome 0 de la spécification XML Schema n'est qu'une introduction et n'est pas un document normatif. Son objectif est de fournir un texte facilement compréhensible des fonctions offertes par XML Schema pour comprendre comment créer des schémas avec le langage XML Schema. Les documents normatifs XML Schema tome 1 : Structures et XML Schema tome 2 : Types de données contiennent une description complète et formelle de la norme. Dans cette introduction, les fonctions du langage sont décrites au travers d'un grand nombre d'exemples complétés par des renvois au texte normatif.
Ce chapitre décrit le statut de ce document au moment de sa publication. D'autres documents peuvent être plus récents que celui-ci. Le dernier statut en date de ce document est tenu à jour par le w3c.
Ce document a été contrôlé par les personnes concernées par le sujet, membres du W3C et autres, et a été validé par le directeur du W3C en tant que recommandation. Il s'agit donc d'un document stable qui peut être utilisé comme document de référence. Le rôle des recommandations du W3C est d'attirer l'attention sur la spécification et d'en promouvoir largement le déploiement. Cela dans le but d'améliorer le fonctionnement et l'interopérabilité du Web.
Ce document a été produit par le groupe de travail sur XML Schema au titre de l'activité XML du W3C. Les objectifs du langage XML Schema sont présentés dans le document de spécification de XML Schema. Les auteurs de ce document sont les membres du groupe de travail sur XML Schema. Les différents tomes ont chacun leurs propres éditeurs.
Cette version intègre les remarques correctives faites sur les versions antérieures.
Vous voudrez bien faire remonter les erreurs trouvées dans ce document à www-xml-schema-comments@w3.org (archive) (ou directement à la traduction française mentionnée en début de document) La liste des erreurs connues de la version anglaise de cette spécification est disponible à l'adresse http://www.w3.org/2001/05/xmlschema-errata.
La version anglaise de cette spécification est la seule version normative du présent document. Les informations concernant ses traductions sont disponibles à l'adresse http://www.w3.org/2001/05/xmlschema-translations.
Une liste complète des recommandations actuelles du W3C et d'autres documents techniques peuvent être trouvés à l'adresse http://www.w3.org/TR/.
any
schemaLocation
Ce document, XML Schema tome 0 : introduction, est une description simplifiée du langage de définition des schémas XML qui doit être utilisée parallèlement à la description formelle qui en est faite dans les tomes 1 (Structures) et 2 (Types de données). Les lecteurs supposés de ce document sont les développeurs d'applications amenés à écrire des programmes lisant ou écrivant des documents de type schéma ainsi que les auteurs de schémas qui ont besoin de connaître les fonctionnalités offertes par le langage, en particulier celles qui sont nouvelles par rapport à celles disponibles avec les DTD. Le texte suppose que vous ayez une connaissance de base de XML 1.0 et de XML-Namespaces. Chaque chapitre de cette introduction à XML Schema traite des nouvelles fonctionnalités du langage en s'appuyant sur des cas concrets.
Le chapitre 2 couvre les mécanismes de base de XML Schema. Il aborde les sujets suivants : la déclaration des éléments et des attributs destinés à être utilisés dans des documents XML, les différences entre les types simples et complexes, la manière de définir des types complexes, l'utilisation des types simples comme valeurs d'éléments et d'attributs, l'annotation des schémas, la présentation d'un mécanisme simple de réutilisation des définitions d'éléments et d'attributs et les valeurs nulles.
Le chapitre 3, le premier des chapitres avancés de cette introduction, concerne les concepts élémentaires régissant l'utilisation des espaces de noms dans les schémas XML et les documents. Ce chapitre est important pour comprendre la plupart des sujets qui sont abordés dans les chapitres avancés II et III.
Le chapitre 4, le deuxième des chapitres avancés de cette introduction, décrit les mécanismes de dérivation des types à partir des types fournis par XML Schema et de contrôle de ces dérivations. Le chapitre décrit aussi les mécanismes de fusion de fragments de schéma issus de plusieurs sources et de substitution d'éléments.
Le chapitre 5 couvre des mécanismes encore plus avancés, comprenant un mécanisme de spécification de l'unicité de certains attributs ou éléments, un mécanisme d'utilisation des types à travers plusieurs espaces de noms, un mécanisme d'extension des types basés sur les espaces de noms et une description du mécanisme de contrôle de la conformité des documents.
En plus des chapitres qui viennent d'être décrits, l'introduction contient un certain nombre d'annexes qui fournissent des informations de référence précises sur les types simples et le langage des expressions régulières.
L'introduction n'est pas un document normatif, ce qui signifie qu'elle n'est pas une spécification définitive du langage XML Schema (du point de vue du W3C). Les exemples et autres supports des explications fournies dans ce document sont fournis pour vous aider à comprendre XML Schema, mais peuvent ne pas fournir de réponse définitive à vos questions. Dans ce cas, vous aurez besoin de vous reporter à la spécification de XML Schema, et pour vous aider à le faire, nous fournissons de nombreux liens vers les parties concernées des tomes 1 et 2 de la spécification. Plus précisément, les items de XML Schema mentionnés dans cette introduction sont reliés à un index des noms d'éléments et d'attributs ainsi qu'à un tableau résumé des types de données, tous les deux étant physiquement dans cette introduction. Le tableau et l'index contiennent des liens aux parties concernées des parties 1 et 2 de la spécification XML Schema.
L'objet de ce schéma est de définir une classe de documents XML : le terme d'instance de document est souvent utilisé pour désigner un fichier contenant un document XML conforme à un schéma particulier. En fait, ni les instances ni les schémas n'ont besoin d'exister physiquement sous la forme de documents stockés dans des fichiers -- ils peuvent exister en tant que flots de données échangés entre deux applications, des champs d'une base de données ou comme des collections d'ensembles d'informations, des "granules d'informations" -- mais pour simplifier cette introduction, nous avons choisi de ne faire référence qu'à des instances et des schémas considérés sous la forme de documents et de fichiers.
Commençons par considérer une instance de document dans un fichier appelé
po.xml
. Elle contient la description d'un
bon de commande émis par une personne privée et une application de
facturation :
<?xml version="1.0"?> <purchaseOrder orderDate="1999-10-20"> <shipTo country="US"> <name>Alice Smith</name> <street>123 Maple Street</street> <city>Mill Valley</city> <state>CA</state> <zip>90952</zip> </shipTo> <billTo country="US"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <city>Old Town</city> <state>PA</state> <zip>95819</zip> </billTo> <comment>Hurry, my lawn is going wild!</comment> <items> <item partNum="872-AA"> <productName>Lawnmower</productName> <quantity>1</quantity> <USPrice>148.95</USPrice> <comment>Confirm this est electric</comment> </item> <item partNum="926-AA"> <productName>Baby Monitor</productName> <quantity>1</quantity> <USPrice>39.98</USPrice> <shipDate>1999-05-21</shipDate> </item> </items> </purchaseOrder>
Le bon de commande est constitué d'un élément principal,
purchaseOrder
, et des sous-éléments shipTo
,
billTo
, comment
et items
. Ceux-là (à
l'exception de l'élément comment
) contiennent à leur tour
d'autres sous-éléments, et ainsi de suite, jusqu'à ce qu'un sous-élément
comme par exemple USPrice
contienne un nombre plutôt qu'un
sous-élément. On dit que les éléments qui contiennent des sous-éléments ou
portent des attributs sont de type complexe, tandis que les éléments qui
contiennent des nombres (ou des chaînes de caractères, des dates, etc.) sans
autre sous-élément sont de type simple. Quelques éléments ont des attributs
; les attributs sont toujours de type simple.
Dans une instance de document, les types complexes et une partie des types simples qui y sont utilisés sont définis dans le schéma associé. Les autres types simples sont ceux qui sont prédéfinis par XML Schema.
Avant d'aller plus en avant dans l'analyse du schéma des bons de commande, nous allons digresser momentanément pour parler de l'association entre une instance et le schéma du bon de commande. Comme vous pouvez vous en apercevoir en regardant une instance de document, le schéma du bon de commande n'est pas mentionné. Il n'est pas pour l'instant obligatoire que les instances référencent les schémas et même si cela sera fait dans de nombreux cas, nous avons choisi de simplifier ce premier chapitre et de considérer que n'importe quel programme de traitement de l'instance saura accéder au schéma correspondant sans avoir besoin que l'information soit écrite en dur dans l'instance. Dans les chapitres suivants, nous introduirons les mécanismes explicites qui permettent d'associer une instance à un schéma.
Le schéma d'un bon de commande est contenu dans le fichier po.xsd
:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:annotation> <xsd:documentation xml:lang="en"> Purchase order schema Par exemple.com. Copyright 2000 exemple.com. All rights reserved. </xsd:documentation> </xsd:annotation> <xsd:element name="purchaseOrder" type="PurchaseOrderType"/> <xsd:element name="comment" type="xsd:string"/> <xsd:complexType name="PurchaseOrderType"> <xsd:sequence> <xsd:element name="shipTo" type="USAddress"/> <xsd:element name="billTo" type="USAddress"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="items" type="Items"/> </xsd:sequence> <xsd:attribute name="orderDate" type="xsd:date"/> </xsd:complexType> <xsd:complexType name="USAddress"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="street" type="xsd:string"/> <xsd:element name="city" type="xsd:string"/> <xsd:element name="state" type="xsd:string"/> <xsd:element name="zip" type="xsd:decimal"/> </xsd:sequence> <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/> </xsd:complexType> <xsd:complexType name="Items"> <xsd:sequence> <xsd:element name="item" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="productName" type="xsd:string"/> <xsd:element name="quantity"> <xsd:simpleType> <xsd:restriction base="xsd:positiveInteger"> <xsd:maxExclusive value="100"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="USPrice" type="xsd:decimal"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/> </xsd:sequence> <xsd:attribute name="partNum" type="SKU" use="required"/> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> <!-- Stock Keeping Unit, one code for identifying products --> <xsd:simpleType name="SKU"> <xsd:restriction base="xsd:string"> <xsd:pattern value="\d{3}-[A-Z]{2}"/> </xsd:restriction> </xsd:simpleType> </xsd:schema>
Le schéma des bons de commande est constitué d'un élément schema
et d'une variété de sous-éléments,
les principaux étant element
,
complexType
, et simpleType
qui déterminent l'ordre
d'apparition des éléments dans l'instance et leurs types de contenu.
Chacun des éléments du schéma est préfixé par
xsd:
associé à l'espace de noms du schéma XML utilisé par le
biais de la déclaration
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
qui est un attribut
de l'élément schema
. Le préfixe
xsd:
est couramment utilisé pour identifier l'espace de noms des
schémas XML alors que n'importe quelle valeur de préfixe pourrait, en
réalité, être utilisée. Le même préfixe et par conséquence la même
association, apparaît également sur les noms des types simples préconstruits,
par exemple xsd:string
. Dans ce cas, le
but de cette association est d'affirmer que les éléments et les types simples
ainsi préfixés appartiennent au vocabulaire du langage XML Schema et non au
vocabulaire particulier de l'auteur du schéma. Pour la lisibilité du texte,
nous ne faisons que mentionner les noms des éléments et des types simples
(par exemple simpleType
) en
omettant leur préfixe.
Dans XML Schema, il y un une différence de base entre les éléments de type complexe qui peuvent contenir des sous-éléments et être qualifiés par des attributs et ceux de type simple qui ne peuvent contenir ni sous-éléments ni être qualifiés par des attributs. Il y un également une distinction majeure entre les définitions qui servent à créer de nouveaux types (qu'ils soient de type simple ou complexe) et les déclarations qui servent à spécifier les noms et les types des éléments et attributs qui pourront être utilisés dans les instances de documents. Dans ce chapitre, nous nous concentrons sur les définitions de types complexes et les déclarations d'éléments et d'attributs qu'elles contiennent.
Les nouveaux types complexes sont créés en utilisant
l'élément complexType
composé, dans la plupart des cas, d'une série de déclarations d'éléments et
d'attributs et de références d'éléments. Les déclarations ne sont pas elles
mêmes des types mais plutôt des associations faites entre un nom et des
contraintes qui régissent les règles d'apparition de l'élément dans une
instance de document correspondant au schéma. Les éléments sont déclarés en
utilisant l'élément element
et
les attributs sont déclarés en utilisant l'élément attribute
. Par exemple, l'élément
USAddress
est défini comme étant de type complexe et, à
l'intérieur de sa définition, nous remarquons la présence de cinq
déclarations d'éléments et d'une déclaration d'attribut :
<xsd:complexType name="USAddress" > <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="street" type="xsd:string"/> <xsd:element name="city" type="xsd:string"/> <xsd:element name="state" type="xsd:string"/> <xsd:element name="zip" type="xsd:decimal"/> </xsd:sequence> <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/> </xsd:complexType>
La conséquence de cette définition est que toute
instance de cet élément dans l'instance (par exemple shipTo
du
fichier po.xml
) doit être constituée de
cinq éléments et d'un attribut. Ces éléments doivent être appelés
name
, street
, city
, state
et zip
conformément à ce qui est spécifié par les différentes
valeurs de l'attribut name
des déclarations de l'exemple
ci-dessus. Ces cinq éléments doivent apparaître dans le même ordre que celui
dans lequel ils sont déclarés dans le schéma. Les quatre premiers
contiendront chacun une chaîne de caractères tandis que le cinquième
contiendra un nombre. Les éléments qui auront USAddress
comme
type déclaré pourront recevoir un attribut appelé country
qui
devra alors avoir comme seul et unique contenu la chaîne de caractère
US
.
La définition de USAddress
ne contient que
des déclarations impliquant des types simples : string
, decimal
et NMTOKEN
. Par opposition, la définition
de PurchaseOrderType
contient des déclarations d'éléments
impliquant des types complexes, par exemple USAddress
. Remarquez
toutefois que dans les deux cas, c'est le même attribut type
qui est utilisé pour identifier le
type, que ce dernier soit simple ou complexe.
<xsd:complexType name="PurchaseOrderType"> <xsd:sequence> <xsd:element name="shipTo" type="USAddress"/> <xsd:element name="billTo" type="USAddress"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="items" type="Items"/> </xsd:sequence> <xsd:attribute name="orderDate" type="xsd:date"/> </xsd:complexType>
Dans la définition de PurchaseOrderType
, les déclarations des
deux éléments shipTo
et billTo
s'appuient sur le
même type complexe USAddress
. La conséquence de cette définition
est que tout élément d'une instance de document (telle que po.xml
) dont le type déclaré est
PurchaseOrderType
doit contenir les éléments shipTo
et billTo,
chacun contenant à leur tour les cinq sous-éléments
(name
, street
, city
,
state
et zip
) déclarés dans la définition de
USAddress
. Les éléments shipTo
et
billTo
peuvent également recevoir l'attribut
country
qui fait partie de la définition de
USAddress
.
La définition de PurchaseOrderType
contient la déclaration de
l'attribut orderDate
qui, comme ce fut le cas pour l'attribut
country
, utilise un type simple. En fait, toutes les
déclarations d'attributs ne peuvent que référencer des types simples car,
contrairement aux éléments, les attributs ne peuvent pas contenir eux-mêmes
d'autres attributs ou éléments.
Les déclarations d'éléments dont nous avons parlé jusque ici sont toutes composées d'une association entre un nom et une définition de type existante. Quelquefois il est préférable d'utiliser un élément existant plutôt que d'en déclarer un nouveau, par exemple:
<xsd:element ref="comment" minOccurs="0"/>
Cette déclaration utilise un élément déjà défini par ailleurs dans le
schéma des bons de commande dont le nom est comment
. En général,
la valeur de l'attribut ref
doit
être celle d'un élément global, c'est à dire un élément déclaré directement à
l'intérieur de schema
et non à
l'intérieur d'une définition de type complexe. La conséquence est qu'un
élément appelé comment
peut être présent dans une instance de
document et que son contenu doit être conforme à ce type d'élément, à savoir
string
.
Dans PurchaseOrderType
, l'élément
comment
est défini comme étant optionnel par le biais de la
valeur 0 de l'attribut minOccurs
. En général, un élément est
requis quand la valeur de minOccurs
vaut 1 ou plus. Le nombre
maximum de fois qu'un élément peut apparaître est déterminé dans sa
déclaration par la valeur de l'attribut maxOccurs
. Cette valeur peut être un
entier positif comme par exemple 41, ou encore le mot unbounded
qui signifie qu'il n'y a pas de valeur limite. La valeur par défaut dans les
deux cas (minOccurs
et
maxOccurs
) est 1. Par
conséquent, quand l'élément comment
est déclaré sans que
l'attribut maxOccurs
soit
précisé, cela signifie qu'il ne peut pas apparaître plus d'une fois. Soyez
certains que lorsque vous ne précisez que la valeur de l'attribut minOccurs
, celle-là soit inférieur ou
au plus égale à la valeur par défaut de maxOccurs
, c'est à dire 0 ou 1. A
contrario, si vous ne faites que spécifier une valeur pour le seul attribut
maxOccurs
, vous devez être
certain que cette valeur soit supérieure ou au moins égale à la valeur par
défaut de minOccurs
, c'est à
dire 1 ou plus. Si les deux attributs sont omis, l'élément doit apparaître
exactement une seule fois.
Les attributs peuvent apparaître au maximum une fois
et donc la syntaxe pour spécifier le nombre d'occurrences autorisées d'un
attribut est différente de celle utilisée pour les éléments. En particulier,
les attributs peuvent être déclarés avec l'attribut de spécification use
qui permet d'en préciser la contrainte
d'apparition, les valeurs possibles sont required
(regardez par
exemple la déclaration de l'attribut partNum
dans po.xsd
), optional
, ou même
prohibited
.
Les valeurs par défaut des attributs comme des éléments sont déclarées en
utilisant l'attribut default
, bien que cette attribut ait des
conséquences sensiblement différentes dans chaque cas de figure. Quand une
valeur est déclarée par défaut pour un attribut en particulier, alors cela
signifie que la valeur de l'attribut sera librement précisée dans l'instance
ou, si aucune valeur n'est clairement précisée dans l'instance, alors le
programme de traitement doit considérer que sa valeur est celle déclarée par
défaut dans le schéma. Notez que les valeurs par défaut des attributs n'ont
de sens que si les attributs eux-mêmes sont optionnels, c'est donc une erreur
que de spécifier simultanément une valeur par défaut et une contrainte
d'apparition autre que optional
dans use
.
Le programme de traitement du schéma traite les contenus d'éléments par
défaut de manière sensiblement différente que pour les attributs. Quand un
élément est déclaré comme ayant un contenu par défaut, le contenu de
l'élément dans une instance de document sera celui qui s'y trouve mais si le
contenu de l'élément dans l'instance n'est pas précisé, alors le programme de
traitement du schéma devra considérer que le contenu par défaut s'applique,
il sera alors constitué de l'élément dont le nom est égal à la valeur de
l'attribut default
.
Toutefois, si l'élément n'apparaît pas du tout dans une instance de document,
alors le programme de traitement du schéma ne doit pas chercher à intégrer
son contenu par défaut. En résumé, les différences entre les valeurs par
défaut des attributs et des éléments peuvent être ramenées à : les valeurs
par défaut des attributs s'appliquent quand l'attribut est omis alors que les
valeurs par défaut des éléments s'appliquent quand l'élément est vide.
L'attribut fixed
est utilisé à la fois dans les déclarations
d'éléments et les déclarations d'attributs pour s'assurer que que leurs
valeurs soient mises à une valeur prédéfinie. Par exemple, po.xsd
contient la déclaration de l'attribut
country
, déclaré avec une valeur de type fixed
égale à US
. Cette
déclaration signifie que l'utilisation de l'attribut country
dans une instance de document est optionnelle (la valeur par défaut de
use
est optional
),
mais, si cet attribut apparaît, alors sa valeur doit être US
et,
si l'attribut n'apparaît pas, alors le processeur devra considérer que
l'attribut country
est présent par défaut et que sa valeur est
US
. Remarquez que les concepts de valeur fixe et de valeur par
défaut s'excluent mutuellement, c'est donc une erreur que d'utiliser les
valeurs fixed
et default
dans la même déclaration
d'attribut.
Les valeurs des attributs utilisées dans les déclarations d'éléments et d'attributs pour contraindre leurs règles d'utilisation dans les instances sont résumées dans le Tableau 1.
Tableau 1. Contraintes d'occurrence des éléments et des attributs | ||
---|---|---|
Eléments (minOccurs, maxOccurs) fixed, default |
Attributs use, fixed, default |
Remarques |
(1, 1) -, - | required, -, - | l'élément ou l'attribut doit apparaître une seule fois, il peut prendre n'importe quelle valeur |
(1, 1) 37, - | required , 37, - |
l'élément ou l'attribut doit apparaître une seule fois, sa valeur doit être 37 |
(2, unbounded) 37, - | non applicable | l'élément doit apparaître deux fois ou plus, sa valeur doit être
37; en général, les valeurs de minOccurs et maxOccurs sont des entiers positifs,
mais maxOccurs peut également
prendre la valeur "unbounded " |
(0, 1) -, - | optional , -, - |
l'élément ou l'attribut peut apparaître 0 ou une fois et peut prendre n'importe quelle valeur |
(0, 1) 37, - | optional , 37, - |
l'élément ou l'attribut peut apparaître 0 ou une fois; quand il apparaît, sa valeur doit être égale à 37; si l'attribut est omis, sa valeur est fixée à 37. Si l'élément est omis, le processeur ne lui impose pas une valeur particulière. |
(0, 1) -, 37 | optional , -, 37 |
l'élément ou l'attribut peut apparaître 0 ou une fois; quand il apparaît, sa valeur est libre; si l'attribut est omis, sa valeur par défaut est 37. Si l'élément est omis, sa valeur n'est pas imposée ; si l'élément est vide, sa valeur est alors 37. |
(0, 2) -, 37 | non applicable | l'élément ou l'attribut peut apparaître 0, une ou deux fois; il n'y un pas de possibilité équivalente pour les attributs. la valeur du contenu de l'élément n'est pas fixée mais si l'élément est vide la valeur considérée par le processeur sera, par défaut, 37; |
(0, 0) -, - | prohibited , -, - |
l'élément ou l'attribut ne doit pas apparaître |
Notez que ni minOccurs, maxOccurs, ni use ne peuvent apparaître dans les déclarations globales d'éléments ou d'attributs. |
Les éléments et les attributs globaux sont créés par des déclarations qui
apparaissent directement à l'intérieur de l'élément schema
. Une fois déclaré, un élément ou un
attribut global peut être référencé dans une ou plusieurs déclarations en
utilisant l'attribut ref
, comme
cela a déjà été vu plus haut. Une déclaration qui référence un élément global
permet à l'élément référencé d'être utilisé dans une instance de document
dans le contexte de la déclaration qui le référence. Aussi, par exemple,
l'élément comment
apparaît dans po.xml
au même niveau que les éléments
shipTo
, billTo
et items
parce que la
déclaration qui référence comment
se trouve dans une définition
de type complexe au même niveau que que les déclarations des trois autres
éléments.
La déclaration d'un élément global permet aussi à l'élément d'être utilisé
au plus haut niveau d'une instance de document, c'est à dire comme élément
racine. Ainsi purchaseOrder
, qui est déclaré comme élément
global dans po.xsd
, peut apparaître comme
élément racine de po.xml
. Remarquez que ce
même raisonnement permettrait également à l'élément comment
d'être utilisé à la racine de po.xml
.
Il y a un certain nombre de pièges concernant l'utilisation des éléments
et des attributs globaux. L'un d'eux est que les déclarations globales ne
peuvent pas contenir de référence ; les déclarations globales doivent
identifier des types simples ou complexes directement. Pour parler
concrètement, les déclarations globales ne peuvent pas utiliser l'attribut
ref
, elles doivent uniquement
utiliser l'attribut type
(ou,
comme nous le décrivons brièvement, être suivies d'une définition de type anonymous
). Un deuxième piège est que
les contraintes de cardinalité ne peuvent pas être posées sur des
déclarations globales alors qu'elles peuvent être utilisées sur des
déclarations locales référençant des déclarations globales. En d'autres
termes, les déclarations globales ne peuvent pas faire appel aux attributs
minOccurs, maxOccurs, ou use.
Nous avons maintenant décrit la manière de définir de nouveaux types
complexes (par exemple PurchaseOrderType
), déclarer des éléments
(par exemple purchaseOrder
) et des attributs (par exemple
orderDate
). Ces actions, en général, impliquent de choisir des
noms, et la question vient ainsi naturellement à être posée : qu'arrive-t-il
si deux objets portent le même nom ? La réponse dépend de la nature des deux
objets en question, en règle général évidemment, plus les deux objets seront
similaires et plus leurs noms seront conflictuels.
Voici quelques exemples pour illustrer les cas où les noms posent
problème. Si les deux objets sont du même type, par exemple, supposons qu'on
ait défini un type complexe baptisé USStates
et un type simple
du même nom, il y a de facto un conflit. Si les deux objets sont de nature
différente, par exemple un élément et un type, disons par exemple qu'on ait
défini un type complexe appelé USAddress
et un élément du même
nom, il n'y aura pas de conflit. Si les deux objets sont déclarés à
l'intérieur de types différents (c'est à dire qu'il ne s'agit pas d'éléments
globaux), par exemple un élément appelé name
à l'intérieur du
type USAddress
et un autre de même nom à l'intérieur du type
Item
, il n'y a pas de conflit de nom (ces déclarations sont
parfois appelées déclarations d'éléments locaux). Finalement, si les deux
objets sont des types dont l'un est défini par vous même et l'autre provienne
de XML Schema, par exemple un type simple appelé decimal
défini
par vous même, il n'y a pas de conflit. La raison de l'apparente
contradiction du dernier exemple est que les deux types appartiennent à des
espaces de noms différents. Nous explorerons l'utilisation des espaces de
noms dans les schémas dans l'un des chapitres qui suivent.
Le schéma de notre bon de commande fait appel à plusieurs éléments et
attributs de types simples. Quelques uns de ces types simples, tels que
string
et decimal
, sont prédéfinis dans XML Schema tandis
que d'autres sont dérivés de ces types pré-éxistants. Par exemple, l'attribut
partNum
a un type appelé SKU
(comme "Stock Keeping
Unit") dérivé de string
. Les types simples
prédéfinis, tout comme leurs dérivées, peuvent être utilisés dans toute
déclaration d'éléments ou d'attributs. Le Tableau
2 liste tous les types simples prédéfinis de XML Schema, en association
avec des exemples d'utilisation des différents types.
Tableau 2. Types simples prédéfinis de XML Schema | ||
---|---|---|
Type simple | exemples (délimités par des virgules) | Remarques |
string | Confirmez que ceci est électrique | |
normalizedString | Confirmez que ceci est électrique | cf (3) |
token | Confirmez que ceci est électrique | cf (4) |
byte | -1, 126 | cf (2) |
unsignedByte | 0, 126 | cf (2) |
base64Binary | GpM7 | |
hexBinary | 0FB7 | |
integer | -126789, -1, 0, 1, 126789 | cf (2) |
positiveInteger | 1, 126789 | cf (2) |
negativeInteger | -126789, -1 | cf (2) |
nonNegativeInteger | 0, 1, 126789 | cf (2) |
nonPositiveInteger | -126789, -1, 0 | cf (2) |
int | -1, 126789675 | cf (2) |
unsignedInt | 0, 1267896754 | cf (2) |
long | -1, 12678967543233 | cf (2) |
unsignedLong | 0, 12678967543233 | cf (2) |
short | -1, 12678 | cf (2) |
unsignedShort | 0, 12678 | cf (2) |
decimal | -1.23, 0, 123.4, 1000.00 | cf (2) |
float | -INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN | équivalent aux nombres flottants simple-précision sur 32-bit, NaN signifie "not un nombre", cf (2) |
double | -INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN | équivalent aux nombres flottants double-précision sur 64-bit, cf (2) |
boolean | true, false 1, 0 |
|
time | 13:20:00.000, 13:20:00.000-05:00 | cf (2) |
dateTime | 1999-05-31T13:20:00.000-05:00 | 31 mai 1999 à 13h20 heure standard de l'Est qui a 5 heures de décalage avec le temps universel, cf (2) |
duration | P1Y2M3DT10H30M12.3S | 1 an, 2 mois, 3 jours, 10 heures, 30 minutes, et 12.3 secondes |
date | 1999-05-31 | cf (2) |
gMonth | --05-- | Mai, cf (2) (5) |
gYear | 1999 | 1999, cf (2) (5) |
gYearMonth | 1999-02 | le mois de février 1999, indépendamment du nombre de jours, cf (2) (5) |
gDay | ---31 | le 31ième jour, cf (2) (5) |
gMonthDay | --05-31 | chaque 31 mai, cf (2) (5) |
Name | shipTo | Type nom de XML 1.0 |
QName | po:USAddress | Nom XML qualifié par un espace de nom |
NCName | USAddress | Nom XML non qualifié ni par un espace de nom ni par le deux points. |
anyURI | http://www.example.com/, http://www.example.com/doc.html#ID5 | |
language | en-GB, en-US, fr | valeurs valides de xml:lang telles que définies dans XML 1.0 |
ID | attribut de type ID tel que défini par XML 1.0, cf (1) | |
IDREF | attribut de type IDREF tel que défini par XML 1.0, cf (1) | |
IDREFS | attribut de type IDREFS tel que défini par XML 1.0, cf (1) | |
ENTITY | attribut de type ENTITY tel que défini par XML 1.0, cf (1) | |
ENTITIES | attribut de type ENTITIES tel que défini par XML 1.0, cf (1) | |
NOTATION | attribut de type NOTATION tel que défini par XML 1.0, cf (1) | |
NMTOKEN | US, Brésil |
attribut de type NMTOKEN tel que défini par XML 1.0, cf (1) |
NMTOKENS | US UK, Brésil Canada Mexique |
attribut de type NMTOKENS tel que défini par XML 1.0, il s'agit d'une suite de NMTOKEN séparés les uns des autres par un espace blanc, cf (1) |
Remarques: (1) Pour conserver la compatibilité
entre XML Schema et les DTD de la version 1.0 de XML, les types
simples ID, IDREF, IDREFS, ENTITY, ENTITIES, NOTATION, NMTOKEN,
NMTOKENS ne doivent être utilisés que pour des attributs. (2) Une
valeur de ce type peut être représentée par plus d'une forme
lexicale, par exemple 100 et 1.0E2 sont deux formats valides de
représentation flottante du nombre cent. Toutefois, des règles ont
été établies pour ce type qui défini une forme lexicale canonique, cf
XML
Schema Part 2. (3) Les caractères retour chariot, tabulation et
changement de ligne du type normalizedString sont
convertis en caractères de type espace avant le traitement du schéma.
(4) Comme pour normalizedString , les séquences de
caractères adjacents de type espace sont ramenés à un seul caractère
espace, et les blancs de tête et de queue sont retirés. (5) Le
préfixe "g" signale une référence temporelle au calendrier
Grégorien. |
Les nouveaux types simples sont définis par dérivation
des types simples déjà existants (ceux qui sont prédéfinis comme ceux qui
sont dérivés). En particulier, on peut dériver un nouveau type simple en
réduisant un type simple existant, en d'autres termes, la fourchette des
valeurs autorisées du nouveau type est un sous-ensemble du type original.
Nous utilisons l'élément de type simpleType
pour définir et nommer le
nouveau type simple. Nous utilisons l'élément restriction
pour indiquer quel est le
type original (appelé type de base) et pour identifier les "facettes" qui
restreignent la fourchette de valeurs. Une liste complète des facettes est
fournie en Annexe B.
Supposez que nous souhaitions créer un nouveau type
d'entier appelé myInteger
dont la fourchette des valeurs
autorisées est comprise entre 10000 et 99999 (inclus). Nous basons notre
définition sur le type simple prédéfini integer
, dont la fourchette de valeurs autorisées
comprend, bien sûr, des valeurs inférieures à 10000 et supérieures à 99999.
Pour définir myInteger
, on restreint la fourchette des valeurs
du type de base integer
en appliquant
deux facettes appelées minInclusive
et maxInclusive
:
myInteger
dont les valeurs autorisées sont
comprises entre 10000 et 99999<xsd:simpleType name="myInteger"> <xsd:restriction base="xsd:integer"> <xsd:minInclusive value="10000"/> <xsd:maxInclusive value="99999"/> </xsd:restriction> </xsd:simpleType>
L'exemple montre une combinaison particulière de l'utilisation d'un type
de base et de deux facettes pour définir myInteger
, mais un
simple regard à la liste des types simples prédéfinis et de leurs facettes
associées de l'annexe B montre d'autres
possibilités de combinaisons pour un résultat identique.
Le schéma des bons de commande contient un autre
exemple, plus sophistiqué, de définition de type simple. Un nouveau type
simple appelé SKU
est dérivé (par restriction) du type simple
string
. De plus, nous contraignons les
valeurs de SKU
en utilisant une facette appelée pattern
combinée à l'application de
l'expression régulière "\d{3}-[A-Z]{2}
" ce qui se lit "trois
chiffres suivis d'un trait d'union suivi de deux lettres majuscules comprises
entre A et Z":
SKU
<xsd:simpleType name="SKU"> <xsd:restriction base="xsd:string"> <xsd:pattern value="\d{3}-[A-Z]{2}"/> </xsd:restriction> </xsd:simpleType>
Le langage des expressions régulières est décrit plus complètement en Annexe D.
XML Schema définit quinze facettes qui sont listées en
Annexe B. Parmis celles-là, la facette
enumeration
est
particulièrement utile et permet d'exprimer des contraintes pour pratiquement
tous les types simples, à l'exception du type boolean
. La facette enumeration
limite un type simple à un
ensemble de valeurs distinctes. Par exemple, nous pouvons utiliser la facette
enumeration
pour définir un
nouveau type simple appelé USState
, dérivé de string
, dont la valeur telle que définie doit être
l'une des abréviations officielles des états américains :
enumeration
:<xsd:simpleType name="USState"> <xsd:restriction base="xsd:string"> <xsd:enumeration value="AK"/> <xsd:enumeration value="AL"/> <xsd:enumeration value="AR"/> <!-- et so on ... --> </xsd:restriction> </xsd:simpleType>
USState
est un bon candidat pour le remplacement du type
string
utilisé dans la déclaration de
l'élément state
. En faisant cette substitution, les valeurs
légales de l'élément state
, plus précisément les sous-éléments
state
de billTo
et shipTo
, seront
limitées à l'une des valeurs AK
, AL
,
AR
, etc. Remarquez que les valeurs de l'énumération, spécifiées
pour un certain type en particulier, doivent être uniques.
XML Schema offre les notions de typage de listes, en plus des si bien
nommés types atomiques qui sont à la base de la plupart des cas de typage
présentés dans le tableau 2. (les types
atomique, liste et union décrits dans le chapitre suivant sont collectivement
appelés des types simples). La valeur d'un type atomique est indivisible du
point de vue de XML Schema. Par exemple, la valeur NMTOKEN
US
est indivisible dans ce
sens qu'aucune partie de US
, comme par exemple le caractère
"S
", n'a de sens intrinsèque propre. Par opposition, les types
liste sont des séries de types atomique ce qui fait que chaque élément d'une
telle séquence (les "atomes") est lui-même significatif du point de vue de
son typage. Par exemple, NMTOKENS
est un
type liste constitué d'une série d'éléments de type NMTOKEN
délimités par un espace blanc faisant
office de séparateur, comme par exemple la suite "US UK FR
". XML
Schema a trois types de listes prédéfinis, il s'agit des types NMTOKENS
, IDREFS
et ENTITIES
.
Pour compléter l'utilisation des types prédéfinis de listes, il est possible de créer de nouveaux types de listes par dérivation des types atomiques existant. (Vous ne pouvez créer de nouveaux types de listes ni à partir des types listes existant, ni à partir des types complexes).
myInteger
<xsd:simpleType name="listOfMyIntType"> <xsd:list itemType="myInteger"/> </xsd:simpleType>
Ce qui pourra donner lieu dans une instance de document à l'exemple suivant :
<listOfMyInt>20003 15037 95977 95945</listOfMyInt>
Plusieurs facettes peuvent être appliquées au type
liste : length
, minLength
, maxLength
, et enumeration
. Par exemple, pour définir
une liste d'exactement six états US (SixUSStates
), nous
commençons par définir un nouveau type liste appelé USStateList
à partir du type USState
que nous dérivons ensuite en
SixUSStates
par restriction de USStateList
à
seulement six items :
<xsd:simpleType name="USStateList"> <xsd:list itemType="USState"/> </xsd:simpleType> <xsd:simpleType name="SixUSStates"> <xsd:restriction base="USStateList"> <xsd:length value="6"/> </xsd:restriction> </xsd:simpleType>
Les éléments dont le type est SixUSStates
doivent avoir six
items et chacun d'eux doit prendre l'une des valeurs atomiques du type
énuméré USState
, par exemple :
<sixStates>PA NY CA NY LA AK</sixStates>
Remarquez qu'il est possible de dériver un type liste à partir du type
atomique string
. Toutefois, un type
string
peut contenir des espaces blancs
alors que ces mêmes espaces blancs servent à délimiter les items d'une liste,
donc vous devez être prudents dans l'utilisation des types liste quand le
type de base est string
. Par exemple,
supposons que nous ayons défini un type liste avec une facette length
égale à 3 et un type de base
string
. La liste de trois items présentée
ci-après est alors valide :
Asie Europe Afrique
Tandis que la liste de trois items présentée ci-après est illégale :
Asie Europe Amérique Latine
Même le terme "Amérique Latine" est légitime en tant que chaîne de caractères à l'extérieur de la liste, il provoque la création d'un quatrième item quand il est inclu dans la liste, l'espace blanc qu'il contient étant considéré comme séparateur. Cela rend le contenu de l'élément invalide par rapport à la contrainte définie dans son modèle (trois items maximum).
Les types atomique et liste permettent à un élément ou
une valeur d'attribut d'être composés de une ou plusieurs instances d'un type
atomique. Par contraste, un type union permet à un élément ou valeur
d'attribut d'être composés d'une ou plusieurs instances d'un type résultant
de l'union de plusieurs types atomique ou liste. Pour donner un exemple, nous
allons créer un type union pour représenter les états américains par des
bigrammes ou des listes de valeurs numériques. Le type union appelé dans
notre exemple zipUnion
est construit à partir d'un type atomique
et d'un type liste :
<xsd:simpleType name="zipUnion"> <xsd:union memberTypes="USState listOfMyIntType"/> </xsd:simpleType>
Quand nous définissons un type union, la valeur de l'attribut
memberTypes
est une liste de tous les types constituant
l'union.
Maintenant, imaginez que nous ayons déclaré un élément appelé
zips
de type zipUnion
, des instances valides de cet
élément pourraient être :
<zips>CA</zips>
<zips>95630 95977 95945</zips>
<zips>AK</zips>
Deux facettes, pattern
et
enumeration
, peuvent être
appliquées à un type union.
Les schémas peuvent être construits en définissant d'abord des ensembles
de types nommés comme par exemple PurchaseOrderType
puis en
déclarant des éléments tels que purchaseOrder
qui référencent
les types en utilisant le constructeur type
. Cette forme de construction de schéma
est directe mais peut être non maniable, spécialement si vous définissez de
nombreux types référencés seulement une fois et contenant très peu de
contraintes. Dans ce cas, un type peut être plus efficacement défini sous la
forme d'un type anonyme qui économise le travail de nommage explicite du type
et de son référencement.
La définition du type Items
dans po.xsd
contient deux déclarations d'éléments qui
utilisent des types anonymes (item
et quantité
). En
général, vous pouvez identifier les types anonymes en notant l'absence de
l'attribut type
dans les
déclarations d'éléments ou d'attributs, et par la présence d'une définition
de type (simple ou complexe) sans nommage particulier :
<xsd:complexType name="Items"> <xsd:sequence> <xsd:element name="item" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="productName" type="xsd:string"/> <xsd:element name="quantity"> <xsd:simpleType> <xsd:restriction base="xsd:positiveInteger"> <xsd:maxExclusive value="100"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="USPrice" type="xsd:decimal"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/> </xsd:sequence> <xsd:attribute name="partNum" type="SKU" use="required"/> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType>
L'élément item
a un type anonyme complexe constitué des
éléments productName
, quantité
,
USPrice
, comment
et shipDate
et d'un
attribut appelé partNum
. L'élément quantity
a un
type anonyme simple dérivé du type integer
dont la fourchette de valeurs est comprise
entre 1 et 99.
Le schéma du bon de commande montre plusieurs cas de contenus : des
éléments sans attribut dont le contenu est constitué de sous-éléments (par
exemple items
), des éléments avec attributs et un contenu formé
de sous-éléments (par exemple shipTo
) et enfin des éléments
contenant seulement un type simple de valeurs (par exemple
USPrice
). Toutefois, nous n'avons vu ni élément ayant des
attributs mais ne contenant qu'un type simple de valeurs, ni élément ayant un
contenu mixte (c'est à dire pouvant contenir à la fois des caractères de
données mélangés à des sous-éléments), ni élément vide (n'ayant aucun contenu
du tout). Dans ce chapitre, nous allons examiner ces cas particuliers de
modèles de contenu.
Tout d'abord, considérons la manière de déclarer un élément ayant un attribut et contenant une valeur simple. Dans une instance, un tel élément pourrait être écrit par exemple :
<internationalPrice currency="EUR">423.46</internationalPrice>
Pour la suite de notre explication, nous allons utiliser le cas de
l'élément USPrice
, déclaré comme suit dans le schéma du bon de
commande :
<xsd:element name="USPrice" type="decimal"/>
Comment ajouter un attribut à cet élément ? Il est de
type simple decimal
et, comme nous
l'avons dit plus haut, ces types ne peuvent avoir d'attribut. A partir de là,
nous devons définir un type complexe pour incorporer la déclaration de
l'attribut. Nous voulons aussi que le contenu de l'attribut soit de type
decimal
. Donc, notre question originale
devient : Comment définit-on un type complexe basé sur le type simple
decimal
? La réponse est obtenue en
dérivant un nouveau type complexe à partir du type simple decimal
comme ceci :
<xsd:element name="internationalPrice"> <xsd:complexType> <xsd:simpleContent> <xsd:extension base="xsd:decimal"> <xsd:attribute name="currency" type="xsd:string"/> </xsd:extension> </xsd:simpleContent> </xsd:complexType> </xsd:element>
Nous utilisons l'élément complexType
pour commencer la
définition du nouveau type (en l'occurrence, il s'agit d'un type anonyme).
Pour indiquer que le modèle de contenu du nouveau type ne contient que des
caractères de données et aucun élément, on utilise l'élément facette simpleContent
. Finalement, nous
dérivons le nouveau type en étendant le type simple decimal
. L'extension consiste à rajouter un
attribut currency
en utilisant une déclaration d'attribut
standard (les dérivations de types sont détaillées au chapitre
4). L'élément internationalPrice
déclaré de la sorte
apparaîtra dans l'instance tel que montré au début de ce chapitre.
La construction du schéma des bons de commande peut être caractérisée comme étant basée sur des éléments imbriqués, les plus profonds d'entre eux (les feuilles) ne contenant que des données textuelles. XML Schema fournit aussi la possibilité de construire des schémas dans lesquels les caractères de données peuvent apparaître au même niveau que des sous-éléments, n'étant pas ainsi confinés au niveau des feuilles de l'arborescence : nous parlons alors de contenu mixte.
Pour illustrer ce propos, on considère l'extrait suivant, provenant d'une lettre d'un client dans laquelle il utilise quelques éléments issus du bon de commande :
<letterBody> <salutation>Dear Mr.<name>Robert Smith</name>.</salutation> Your order of <quantity>1</quantity> <productName>Baby Monitor</productName> shipped from our warehouse on <shipDate>1999-05-21</shipDate>. .... </letterBody>
Remarquez que dans l'élément salutation
, du texte est mélangé
à des éléments enfants. Plus précisément, du texte apparaît entre les
éléments salutation
, quantity
,
productName
et shipDate
qui sont tous des enfants
de l'élément letterBody
. L'extrait suivant est la partie du
schéma où est déclaré letterBody
:
<xsd:element name="letterBody"> <xsd:complexType mixed="true"> <xsd:sequence> <xsd:element name="salutation"> <xsd:complexType mixed="true"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="quantity" type="xsd:positiveInteger"/> <xsd:element name="productName" type="xsd:string"/> <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/> <!-- etc. --> </xsd:sequence> </xsd:complexType> </xsd:element>
Les éléments qui apparaissent dans la lettre du client sont déclarés et
leurs types sont définis par des montages faits à partir des éléments
element
et complexType
, comme nous l'avons déjà
vu. Pour autoriser que des caractères de données puissent être mélangés aux
éléments enfants de letterBody
, l'attribut mixed
est positionné à true
dans la définition du type.
Remarquez que le modèle mixed
de XML Schema est
fondamentalement différent de celui précédemment défini dans XML
1.0. Avec ce nouveau modèle, l'ordre et le nombre des éléments enfants de
l'instance doivent être en conformité avec ceux spécifiés dans le modèle.
Alors que dans XML 1.0, ils ne pouvaient être imposés. En résumé, XML Schema
fournit une validation complète des modèles de contenu mixte contrastant avec
la validation seulement partielle de XML 1.0.
Maintenant, supposons que nous voulions que l'élément
internationalPrice
ait une unité monétaire et un prix sous la
forme d'un attribut au lieu que cela soit sous la forme d'un contenu :
<internationalPrice currency="EUR" value="423.46"/>
Un tel élément n'a pas de contenu du tout ; son modèle de contenu est vide. Pour définir un type dont le contenu est vide, le principe est de définir un type ne permettant d'avoir que des sous-éléments comme contenu, sous-éléments qui ne seront jamais déclarés.
<xsd:element name="internationalPrice"> <xsd:complexType> <xsd:complexContent> <xsd:restriction base="xsd:anyType"> <xsd:attribute name="currency" type="xsd:string"/> <xsd:attribute name="value" type="xsd:decimal"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> </xsd:element>
Dans cet exemple, nous définissons un type anonyme ayant un contenu de
type complexContent
, c'est à dire uniquement constitué
d'éléments. L'élément complexContent
indique que nous avons
l'intention de restreindre ou d'étendre le modèle de contenu et la
restriction
à anyType
permet de déclarer deux
attributs mais n'introduit aucun sous-élément (cf Chapitre 4.4 pour plus de détails sur les
restrictions). L'élément internationalPrice
ainsi déclaré peut
légitimement apparaître dans une instance sous la forme montrée dans
l'exemple ci-dessus.
La syntaxe précédemment utilisée pour déclarer un élément vide est
relativement verbeuse et il est possible de déclarer l'élément
internationalPrice
d'une manière plus compacte.
<xsd:element name="internationalPrice"> <xsd:complexType> <xsd:attribute name="currency" type="xsd:string"/> <xsd:attribute name="value" type="xsd:decimal"/> </xsd:complexType> </xsd:element>
Cette syntaxe compacte marche parce que la définition d'un type complexe
sans utilisation aucune de simpleContent
ou
complexContent
est interprétée comme étant un raccourci pour
définir un contenu complexe réduit à anyType
.
Le mot anyType
représente une abstraction appelée ur-type
qui est le type de base à partir duquel tous les types simples et complexes
sont dérivés. Un type anyType
ne contraint un contenu d'aucune
manière. Il est possible d'utiliser anyType
comme n'importe quel
autre type, par exemple :
<xsd:element name="anything" type="xsd:anyType"/>
Le contenu de l'élément déclaré de cette manière n'est pas contraint, la
valeur de l'élément peut donc être 423.46 comme n'importe quelle autre
séquence de caractères, ou un mélange de caractères et de sous-éléments. En
fait, anyType
est le type par défaut quand aucun type n'est
spécifié, aussi, l'exemple précédent pourrait s'écrire comme suit :
<xsd:element name="anything"/>
Si un contenu d'élément libre est nécessaire, par exemple dans le cas où
il est nécessaire d'embarquer du balisage étranger dans un élément, alors la
déclaration par défaut ou une forme légèrement restreinte peut être pratique.
Le type text
décrit au Chapitre 5.5 est
un exemple d'un tel type.
XML Schema fournit trois éléments dont l'objectif est
de commenter les schémas de manière à ce que les commentaires puissent être
lus aussi bien par des humains que par des applications. Dans le cas du
schéma des bons de commande, nous mettons une description sommaire du schéma
ainsi qu'une information de copyright à l'intérieur de l'élément documentation
, ce qui est l'endroit
recommandé pour les commentaires à destination des lecteurs. Nous
recommandons d'utiliser l'attribut xml:lang
avec tout élément
documentation
pour en
préciser la langue d'écriture. Une autre manière de faire consiste à placer
cet attribut sur l'élément de plus haut niveau, schema
, pour
indiquer que la langue précisée s'applique à tous les commentaires présents
dans le schéma.
L'élément appInfo
, que nous n'avons pas utilisé dans
le schéma des bons de commande, peut être utilisé pour transmettre de
l'information aux outils, feuilles de styles et autres applications qui en
auraient besoin. Un exemple intéressant utilisant appInfo
est le schéma
décrivant les types simples de XML Schema (cf le tome 2). Les informations de
description de ce schéma, faites à l'intérieur d'éléments appInfo
, présentent les facettes
applicables à des types simples en particulier, ont été reprises
automatiquement par un programme pour produire le texte du tome 2 de XML
Schema.
Les deux éléments documentation
et appInfo
apparaissent comme des
sous-éléments de annotation
,
qui pourrait lui-même apparaître au début de bien des schémas. Pour illustrer
ce propos, l'exemple suivant montre l'utilisation d'éléments annotation
au début d'une déclaration
d'élément et d'une définition d'un type complexe :
<xsd:element name="internationalPrice"> <xsd:annotation> <xsd:documentation xml:lang="en"> élément déclaré with anonymous type </xsd:documentation> </xsd:annotation> <xsd:complexType> <xsd:annotation> <xsd:documentation xml:lang="en"> empty anonymous type with 2 attributs </xsd:documentation> </xsd:annotation> <xsd:complexContent> <xsd:restriction base="xsd:anyType"> <xsd:attribute name="currency" type="xsd:string"/> <xsd:attribute name="value" type="xsd:decimal"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType> </xsd:element>
L'élément annotation
peut
aussi apparaître au début d'autres structures de schémas telles que celles
des éléments schema
, simpleType
, et attribute
.
Dans le schéma des bons de commande, les types complexes sont tous définis
avec des séquences d'éléments devant apparaître dans les instances. Les
occurrences des éléments individuellement déclarés dans ces modèles peuvent
être optionnelles, comme cela est le cas quand l'attribut minOccurs
vaut 0 (par exemple dans
comment
) ou être contrainte de diverses manières en fonction des
valeurs de minOccurs
et
maxOccurs
. XML Schema permet
aussi d'exprimer des contraintes s'appliquant aux groupes d'éléments des
modèles de contenu. Ces contraintes reflètent celles disponibles avec XML 1.0
et les complètent par quelques restrictions supplémentaires. Remarquez que
les contraintes ne s'appliquent pas aux attributs.
XML Schema permet de créer et de nommer des groupes d'éléments afin que les éléments puissent être utilisés pour construire les modèles de contenu de type complexe (singeant ainsi le mécanisme des entités paramètres de XML 1.0). Des groupes anonymes d'éléments peuvent également être définis qui, comme les éléments des groupes nommés, peuvent être contraints d'apparaître dans le même ordre (séquence) que leur ordre de déclaration. D'un autre côté, ils peuvent être contraints de manière à ne laisser qu'un seul de ces éléments apparaître dans une instance.
Pour donner un exemple, nous introduisons deux groupes
dans la définition du type PurchaseOrderType
du schéma des bons
de commande de telle manière que les bons de commande puissent contenir au
choix une ou deux adresses distinctes de facturation et de livraison :
<xsd:complexType name="PurchaseOrderType"> <xsd:sequence> <xsd:choice> <xsd:group ref="shipAndBill"/> <xsd:element name="singleUSAddress" type="USAddress"/> </xsd:choice> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="items" type="Items"/> </xsd:sequence> <xsd:attribute name="orderDate" type="xsd:date"/> </xsd:complexType> <xsd:group name="shipAndBill"> <xsd:sequence> <xsd:element name="shipTo" type="USAddress"/> <xsd:element name="billTo" type="USAddress"/> </xsd:sequence> </xsd:group>
Le groupe choice
signifie qu'un
seul de ses éléments enfants pourra apparaître dans l'instance. Le premier
des enfants est défini via l'élément group
qui référence le groupe nommé
shipAndBill
, lui-même formé des éléments shipTo
et
billTo
dans cet ordre et le deuxième élément du groupe est
singleUSAddress
. Il s'ensuit que dans une instance de document
conforme à ce schéma, l'élément purchaseOrder
contiendra soit
une suite composée des éléments shipTo
et billTo
soit le seul élément singleUSAddress
. Le groupe choice
est ensuite suivi par les deux
déclarations des éléments comment
et items
et tous
sont des enfants de l'élément sequence
. L'effet de ces différentes
imbrications de groupes est que tout élément address
doit être
suivi des éléments comment
et items
dans cet
ordre.
Une troisième type de contrainte de groupe : tous les
éléments du groupe peuvent apparaître une fois mais dans n'importe quel
ordre. L'usage du groupe all
(version
simplifiée du connecteur SGML &) est limité au plus haut niveau de tout
modèle de contenu. Les enfants du groupe doivent tous être des éléments
individuels (pas de sous-groupe) et aucun élément du modèle de contenu ne
peut apparaître plus d'une fois, c'est à dire que les seules valeurs
autorisées de minOccurs
et
maxOccurs
sont 0 et 1. Par
exemple, pour permettre aux éléments enfants de purchaseOrder
d'apparaître dans n'importe quel ordre, nous pourrions redéfinir
PurchaseOrderType
comme ceci :
all
<xsd:complexType name="PurchaseOrderType"> <xsd:all> <xsd:element name="shipTo" type="USAddress"/> <xsd:element name="billTo" type="USAddress"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="items" type="Items"/> </xsd:all> <xsd:attribute name="orderDate" type="xsd:date"/> </xsd:complexType>
Par cette définition, un élément comment
peut apparaître dans
purchaseOrder
(sans toutefois être obligatoire) avant ou après
n'importe lequel des autres éléments shipTo
, billTo
et items
du modèle de contenu. Il ne pourra de toute façon
n'apparaître qu'une seule fois. De plus, il est stipule que dans le cas du
groupe all
nous ne pouvons déclarer
un élément tel que comment
en dehors du groupe comme moyen de
contournement pour lui permettre d'apparaître plus d'une fois. XML Schema
stipule en effet qu'un groupe all
doit apparaître comme seul et unique enfant de premier niveau d'un modèle de
contenu. En d'autres termes, la forme suivante est interdite parce que le
groupe all
qu'elle contient n'est pas
le seul et unique enfant de premier niveau de la définition du type
PurchaseOrderType
:
All
:<xsd:complexType name="PurchaseOrderType"> <xsd:sequence> <xsd:all> <xsd:element name="shipTo" type="USAddress"/> <xsd:element name="billTo" type="USAddress"/> <xsd:element name="items" type="Items"/> </xsd:all> <xsd:sequence> <xsd:element ref="comment" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:sequence> <xsd:attribute name="orderDate" type="xsd:date"/> </xsd:complexType>
Finalement, les groupes nommés ou non qui apparaissent dans les modèles de
contenu (représenté respectivement par group
, choice
, sequence
, all
) peuvent être porteurs des attributs
minOccurs
et maxOccurs
. En combinant et en
entrelaçant les différents types de groupes fournis par XML Schema et en
fixant les valeurs de minOccurs
et maxOccurs
, il est possible de
représenter tous les modèles de contenu envisageables avec les DTD de XML
1.0. De plus, le groupe all
fournit
une puissance d'expression supérieure.
Remarque de la traduction française :
Il semblerait que, pour être encore plus explicite, l'exemple ci-dessus devrait être :
<xsd:complexType name="PurchaseOrderType"> <xsd:sequence> <xsd:all> <xsd:element name="shipTo" type="USAddress"/> <xsd:element name="billTo" type="USAddress"/>
<xsd:element ref="comment" minOccurs="0"/>
<xsd:element name="items" type="Items"/> </xsd:all> <xsd:sequence>
<xsd:element ref="comment" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence> </xsd:sequence> <xsd:attribute name="orderDate" type="xsd:date"/> </xsd:complexType>
Tel que l'exemple est écrit ci-dessus, la déclaration de l'élément comment
apparaît à la fois dans le groupe all
et à l'extérieur. C'est là
que se trouve le véritable problème de cette formulation qui, dans son
application dans les instances de documents, est la cause de formes ambiguës
que les programmes de validation ne savent pas "désambigüifier". Par exemple,
cette formulation autorise d'écrire dans une instance de document :
<PurchaseOrder>
<billTo>adresse de facturation</billTo>
<comment>commentaire</comment>
</PurchaseOrder>
Fragment dont un programme de validation ne saurait déterminer si la
balise <comment>
appartient au groupe all
ou
à la séquence suivante et par conséquent ne saurait valider ce fragment.
Fin de la remarque fait par la traduction française
Supposez que nous voulions fournir plus d'informations sur les articles
qui composent le bon de commande, comme par exemple leur poids et la méthode
d'expédition demandée. Nous pouvons obtenir ce résultat en ajoutant les
déclarations de deux attributs weightKg
et shipBy
à
la définition (de type anonyme) de l'élément item
:
<xsd:element name="Item" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="productName" type="xsd:string"/> <xsd:element name="quantity"> <xsd:simpleType> <xsd:restriction base="xsd:positiveInteger"> <xsd:maxExclusive value="100"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="USPrice" type="xsd:decimal"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/> </xsd:sequence> <xsd:attribute name="partNum" type="SKU" use="required"/> <!-- add weightKg and shipBy attributs --> <xsd:attribute name="weightKg" type="xsd:decimal"/> <xsd:attribute name="shipBy"> <xsd:simpleType> <xsd:restriction base="xsd:string"> <xsd:enumeration value="air"/> <xsd:enumeration value="land"/> <xsd:enumeration value="any"/> </xsd:restriction> </xsd:simpleType> </xsd:attribute> </xsd:complexType> </xsd:element>
Une alternative serait de créer un groupe d'attributs
nommé contenant tous les attributs souhaités de l'élément item
puis de référencer ce groupe dans la déclaration de l'élément
item
:
<xsd:element name="item" minOccurs="0" maxOccurs="unbounded"> <xsd:complexType> <xsd:sequence> <xsd:element name="productName" type="xsd:string"/> <xsd:element name="quantity"> <xsd:simpleType> <xsd:restriction base="xsd:positiveInteger"> <xsd:maxExclusive value="100"/> </xsd:restriction> </xsd:simpleType> </xsd:element> <xsd:element name="USPrice" type="xsd:decimal"/> <xsd:element ref="comment" minOccurs="0"/> <xsd:element name="shipDate" type="xsd:date" minOccurs="0"/> </xsd:sequence> <!-- attributeGroup replaces individual declarations --> <xsd:attributeGroup ref="ItemDelivery"/> </xsd:complexType> </xsd:element> <xsd:attributeGroup name="ItemDelivery"> <xsd:attribute name="partNum" type="SKU" use="required"/> <xsd:attribute name="weightKg" type="xsd:decimal"/> <xsd:attribute name="shipBy"> <xsd:simpleType> <xsd:restriction base="xsd:string"> <xsd:enumeration value="air"/> <xsd:enumeration value="land"/> <xsd:enumeration value="any"/> </xsd:restriction> </xsd:simpleType> </xsd:attribute> </xsd:attributeGroup>
Cette utilisation d'un groupe d'attributs peut améliorer la lisibilité des schémas et faciliter leurs mises à jour parce qu'un groupe d'attributs peut être édité et modifié en une seule fois et être référencé dans de multiples définitions et déclarations. Cette caractéristique des groupes d'attributs est comparable à celle des entités paramètres de XML 1.0. Remarquez qu'un groupe d'attributs peut contenir d'autres groupes d'attributs. Remarquez aussi que les déclarations d'attributs tout comme les références à des groupes d'attributs doivent apparaître à la fin des définitions de types complexes.
Remarque faite par la traduction française :
La mutualisation des déclarations d'attributs et d'éléments au moyen des groupes d'attributs référencés a des limites et la remarque faite ci-dessus sur les facilités de mise à jour peut en réalité se retourner contre l'auteur du schéma lorsque celui-là aura trop usé de cette technique et des possibilités d'imbrication des groupes. Il faut donc faire preuve de discernement dans la mutualisation des définitions. A trop utiliser les groupes, le risque existe réellement d'avoir des schémas peu lisibles. La mise à jour s'avère alors complexe voir impossible (impossibilité de mesurer le réel impact d'une mise à jour sur l'ensemble des déclarations du schéma).
Fin de la remarque faite par la traduction française
L'un des items listés dans le bon de commande du fichier po.xml
, le Lawnmower
, n'a pas
d'élément shipDate
. Dans le contexte de notre scénario, l'auteur
du schéma peut avoir eu l'intention d'autoriser cette absence pour indiquer
les articles dont l'expédition n'a pas encore été effectuée. Mais en général,
l'absence d'un élément n'a pas de signification particulière : cela peut
signifier au choix que l'information est inconnue, ou qu'elle est non
applicable, ou que l'élément est absent pour une quelconque autre raison.
Parfois il est souhaitable de pouvoir représenter un article non expédié, une
information inconnue ou inapplicable par un élément explicitement,
plutôt que par l'absence d'un élément. Par exemple, il peut être souhaitable
de représenter par la présence explicite d'un élément une valeur "nulle"
échangée avec une base de données. De tels cas peuvent être résolus en
utilisant le mécanisme nil
de XML Schema qui permet à un élément
d'apparaître avec ou sans une valeur non-nulle.
Pour cela, le mécanisme nil
met en jeu un
signal nil
indirect. En d'autres termes, il n'y a pas de valeur
nil
apparaissant explicitement au niveau du modèle de contenu.
Au lieu de cela, un attribut sert à indiquer que le contenu de l'élément est
nul. Pour donner un exemple, nous modifions la déclaration de l'élément
shipDate
de telle manière que la valeur nil
puisse
être marquée :
<xsd:element name="shipDate" type="xsd:date" nillable="true"/>
Et pour explicitement représenter que
shipDate
a une valeur nil
dans une instance de
document, il suffit de mettre la valeur de l'attribut nil
à
true
:
<shipDate xsi:nil="true"></shipDate>
L'attribut nil
provient de
l'espace des noms de XML Schema applicables aux instances
http://www.w3.org/2001/XMLSchema-instance
, en conséquence de
quoi il doit être préfixé dans une instance de document du préfixe (tel que
xsi:
) associé à cet espace de noms (comme pour le préfixe
xsd:
, le préfixe xsi:
est utilisé seulement par
convention). Remarquez que le mécanisme nil
ne s'applique qu'aux
contenus d'éléments et pas à la valeur de leurs attributs. Un élément porteur
de la valeur xsi:nil="true"
n'a
aucun contenu mais peut porter d'autres attributs.
Un schéma peut être vu comme une collection (un
vocabulaire) de définitions de types et déclarations d'éléments dont les noms
appartiennent à un espace de noms particulier appelé espace de noms cible.
lls nous permettent de distinguer les définitions et les déclarations
appartenant à des vocabulaires différents. Par exemple, cela nous permet de
faire la distinction entre la déclaration element
du vocabulaire de XML Schema et
celle du même mot element
d'un vocabulaire qui serait spécifique
à une application XML dans le domaine de la chimie. Le premier des deux mots
fait partie de l'espace de noms cible
http://www.w3.org/2001/XMLSchema
et le deuxième ferait partie
d'un autre espace de noms cible.
Quand nous voulons vérifier qu'une instance de document est conforme à un ou plusieurs schémas (au moyen d'un traitement appelé validation de schéma), le programme doit être capable de faire la différence entre les déclarations d'éléments et d'attributs et les définitions de types des différents schémas. L'espace de noms cible joue un rôle important dans le processus d'identification. Nous examinons le rôle de l'espace de noms cible au chapitre suivant.
L'auteur du schéma a aussi plusieurs options à sa disposition pour modifier la manière dont l'identité des éléments et des attributs est représentée dans les instances de documents. Plus précisément, l'auteur peut décider si l'écriture des éléments et des attributs déclarés localement doit être qualifiée par un espace de noms, soit via un préfixe explicite soit une valeur implicite par défaut. Le choix de l'auteur du schéma vis à vis de la qualification des éléments et des attributs locaux a un certain nombre d'impacts sur les structures des schémas et des instances et nous en examinons quelques uns dans les chapitres qui suivent.
Dans une version différente du schéma des bons de commande, po1.xsd
, nous déclarons explicitement un espace de
nom cible et nous spécifions que les éléments et les attributs définis
localement ne doivent pas être qualifiés. L'espace de noms cible de po1.xsd
est
http://www.example.com/PO1
, valeur indiquée par l'attribut
targetNamespace
.
La qualification d'éléments et d'attributs locaux peut être spécifiée soit
globalement via la paire d'attributs elementFormDefault
et
attributeFormDefault
de
l'élément schema
soit
individuellement au niveau de chaque déclaration via l'attribut form
. Ces attributs peuvent prendre soit la
valeur unqualified
soit la valeur qualified
pour
spécifier si les éléments et attributs qui les portent doivent être
qualifiés.
Dans po1.xsd
nous spécifions
globalement la qualification des éléments et des attributs en initialisant
les valeurs des deux attributs elementFormDefault
et
attributeFormDefault
à unqualified
. Stricto
senso, ces initialisations ne sont pas nécessaires parce que les valeurs
utilisées sont celles par défaut; nous les mettons en évidence uniquement
pour bien souligner la différence avec d'autres cas que nous verrons plus
loin.
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:po="http://www.example.com/PO1" targetNamespace="http://www.example.com/PO1" elementFormDefault="unqualified" attributeFormDefault="unqualified"> <element name="purchaseOrder" type="po:PurchaseOrderType"/> <element name="comment" type="string"/> <complexType name="PurchaseOrderType"> <sequence> <element name="shipTo" type="po:USAddress"/> <element name="billTo" type="po:USAddress"/> <element ref="po:comment" minOccurs="0"/> <!-- etc. --> </sequence> <!-- etc. --> </complexType> <complexType name="USAddress"> <sequence> <element name="name" type="string"/> <element name="street" type="string"/> <!-- etc. --> </sequence> </complexType> <!-- etc. --> </schema>
Pour voir comment l'espace de noms cible de ce schéma est peuplé, nous
allons examiner tour à tour les définitions de types et les déclarations
d'éléments, en commençant par la fin du schéma. En premier lieu, nous
définissons le type appelé USAddress
qui comprend les éléments
name
, street
, etc. Faisant cela, le type
USAddress
est inclus dans l'espace de noms cible du schéma.
Ensuite, nous définissons le type appelé PurchaseOrderType
qui
comprend les éléments shipTo
, billTo
,
comment
, etc. PurchaseOrderType
est également
inclus dans l'espace de nom cible du schéma. Remarquez que les références de
type dans les trois déclarations d'éléments sont préfixées :
po:USAddress
, po:USAddress
et
po:comment
ont le préfixe po:
, associé à l'espace
de noms http://www.example.com/PO1
, le même que l'espace de noms
cible du schéma. Ainsi, un programme de traitement du schéma saura regarder à
l'intérieur du schéma pour y trouver la définition du type
USAddress
ainsi que la déclaration de l'élément
comment
. Il est également possible de référencer des types
provenant d'autres schémas en utilisant des espaces de noms cibles
différents, permettant ainsi la réutilisation de déclarations et de
définitions.
Au début du schéma po1.xsd
se trouvent
les déclarations des éléments purchaseOrder
et
comment
. Ils sont inclus dans l'espace de noms cible du schéma.
Le type de l'élément purchaseOrder
est préfixé pour la même
raison qui fait que le type USAddress
est préfixé. A contrario,
le type string
de l'élément
comment
n'est pas préfixé. Le schéma po1.xsd
contient une déclaration d'espace de noms
par défaut et par conséquent les types et les éléments sans préfixe tels que
string
, element
et complexType
sont associés à l'espace
de noms par défaut http://www.w3.org/2001/XMLSchema
. En fait,
cela est l'espace de noms cible de XML Schema lui-même, faisant ainsi qu'un
programme de traitement de po1.xsd
saura
regarder à l'intérieur du schéma de XML Schema -- encore connu comme étant
"le schéma des schémas" -- pour y trouver la définition du type string
ainsi que la déclaration de l'élément appelé
element
.
Regardons maintenant comment l'espace de noms cible du schéma a des effets sur une instance de document conforme :
po1.xml
<?xml version="1.0"?> <apo:purchaseOrder xmlns:apo="http://www.example.com/PO1" orderDate="1999-10-20"> <shipTo country="US"> <name>Alice Smith</name> <street>123 Maple Street</street> <!-- etc. --> </shipTo> <billTo country="US"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <!-- etc. --> </billTo> <apo:comment>Hurry, my lawn is going wild!</apo:comment> <!-- etc. --> </apo:purchaseOrder>
Cette instance déclare un espace de nom,
http://www.example.com/PO1
, et l'associe au préfixe
apo:
utilisé pour qualifier deux éléments du document, à savoir
purchaseOrder
et comment
. L'espace de noms est
identique à celui défini comme cible dans le schéma po1.xsd
et un programme de traitement de
l'instance sait qu'il y trouvera leurs déclarations respectives. En fait, le
mot cible a été choisi à cause du sens dans lequel il existe une relation
entre les éléments purchaseOrder
et comment
et
l'espace de noms référencé (note de la rédaction française : le programme de
validation part du nom de l'élément et remonte jusqu'à l'espace de noms cible
associé au préfixe de l'élément). Il s'ensuit que les espaces de noms cibles
du schéma contrôlent la validation des espaces de noms correspondant de
l'instance.
Le préfixe apo:
est appliqué aux éléments globaux
purchaseOrder
et comment
. En plus, les attributs
et
attributeFormDefault
imdiquent que le préfixe n'est pas obligatoire sur les attributs et les
éléments locaux tels que shipTo
, billTo
,
name
et street
. Les éléments
purchaseOrder
et comment
sont globaux parce qu'ils
ont été déclarés dans le schéma de manière générique plutôt que dans le cadre
restrictif d'un type particulier. Par exemple, dans po1.xsd
, la déclaration de
purchaseOrder
est un enfant direct de l'élément schema
alors que celle de
shipTo
est un enfant de l'élément complexType
utilisé pour définir
l'élément PurchaseOrderType
.
Quand la qualification des éléments et des attributs locaux n'est pas
requise, l'auteur d'une instance pourra avoir besoin de plus ou moins de
connaissance sur le schéma pour écrire des documents valides. Plus
précisément, si l'auteur peut être certain que seul l'élément racine (tel que
purchaseOrder
) est global, alors il est simple de n'avoir à
qualifier que l'élément racine. Par contre, l'auteur peut savoir que tous les
éléments ont été déclarés globalement et qu'ils sont donc tous susceptibles
d'être qualifiés, au mieux en profitant d'une déclaration d'espace de noms
par défaut pour simplifier la tâche (cette approche est analysée dans le chapitre 3.3). D'un autre côté, si il n'y a pas de
motif uniforme entre les déclarations globales et locales, alors l'auteur
aura besoin d'avoir une connaissance très précise du schéma pour pouvoir
préfixer correctement les éléments et attributs globaux.
Les éléments et les attributs sont indépendants vis à vis des exigences de
qualification bien que nous commencions par décrire la qualification des
éléments locaux. Pour spécifier que tous les éléments déclarés localement
dans un schéma doivent être qualifiés, on initialise la valeur de elementFormDefault
à
qualified
:
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:po="http://www.example.com/PO1" targetNamespace="http://www.example.com/PO1" elementFormDefault="qualified" attributeFormDefault="unqualified"> <element name="purchaseOrder" type="po:PurchaseOrderType"/> <element name="comment" type="string"/> <complexType name="PurchaseOrderType"> <!-- etc. --> </complexType> <!-- etc. --> </schema>
Et dans cette instance de document conforme, nous qualifions tous les éléments explicitement :
<?xml version="1.0"?> <apo:purchaseOrder xmlns:apo="http://www.example.com/PO1" orderDate="1999-10-20"> <apo:shipTo country="US"> <apo:name>Alice Smith</apo:name> <apo:street>123 Maple Street</apo:street> <!-- etc. --> </apo:shipTo> <apo:billTo country="US"> <apo:name>Robert Smith</apo:name> <apo:street>8 Oak Avenue</apo:street> <!-- etc. --> </apo:billTo> <apo:comment>Hurry, my lawn is going wild!</apo:comment> <!-- etc. --> </apo:purchaseOrder>
Alternativement, nous pouvons remplacer la qualification explicite de
chaque élément par une qualification implicite fournie par un espace de noms
par défaut, comme cela est montré ci-dessous dans po2.xml
:
<?xml version="1.0"?> <purchaseOrder xmlns="http://www.example.com/PO1" orderDate="1999-10-20"> <shipTo country="US"> <name>Alice Smith</name> <street>123 Maple Street</street> <!-- etc. --> </shipTo> <billTo country="US"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <!-- etc. --> </billTo> <comment>Hurry, my lawn is going wild!</comment> <!-- etc. --> </purchaseOrder>
Dans po2.xml
, tous les éléments de
l'instance appartiennent au même espace de noms et la déclaration de l'espace
de noms définit un espace de noms par défaut qui s'applique à tous les
éléments de l'instance. A partir de là, il est inutile de préfixer
explicitement un quelconque élément. Comme autre illustration de
l'utilisation d'éléments qualifiés, les schémas du chapitre 5 exigent tous d'utiliser des éléments
qualifiés.
La qualification des attributs est très similaire à celle des éléments.
Les attributs qui doivent être qualifiés, soit parce qu'ils sont déclarés
globalement soit parce que l'attribut attributeFormDefault
est
initialisé à qualified
, sont préfixés dans les instances des
documents. Un exemple d'attribut qualifié est l'attribut xsi:nil
qui a été introduit au chapitre 2.9. En fait, les attributs qui doivent être
qualifiés doivent être explicitement préfixés parce que la spécification XML-Namespaces
ne fournit aucun mécanisme pour définir un espace de noms par défaut pour les
attributs. Les attributs qui n'ont pas besoin d'être qualifiés apparaissent
dans les instances de documents sans préfixe, ce qui est la cas classique.
Le mécanisme de qualification que nous avons décrit
jusqu'à maintenant a permis de contrôler toutes les déclarations locales
d'éléments et d'attributs à l'intérieur d'un espace de noms cible en
particulier. Il est également possible de contrôler la qualification sur une
déclaration bien précise en utilisant l'attribut form
. Par exemple, pour exiger que
l'attribut déclaré localement publicKey
soit qualifié dans les
instances, nous la déclarons de la manière suivante :
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:po="http://www.example.com/PO1" targetNamespace="http://www.example.com/PO1" elementFormDefault="qualified" attributeFormDefault="unqualified"> <!-- etc. --> <element name="secure"> <complexType> <sequence> <!-- élément declarations --> </sequence> <attribute name="publicKey" type="base64Binary" form="qualified"/> </complexType> </element> </schema>
Remarquez que la valeur de l'attribut form
écrase la valeur par défaut de
l'attribut attributeFormDefault
mais
uniquement pour l'attribut publicKey
. L'attribut form
peut tout aussi bien être appliqué à
une déclaration d'élément. Une instance de document conforme à ce schéma est
par exemple :
<?xml version="1.0"?> <purchaseOrder xmlns="http://www.example.com/PO1" xmlns:po="http://www.example.com/PO1" orderDate="1999-10-20"> <!-- etc. --> <secure po:publicKey="GpM7"> <!-- etc. --> </secure> </purchaseOrder>
Quand tous les noms d'éléments sont uniques à l'intérieur d'un espace de
noms, les schémas faits à partir de cet espace de noms peuvent ne contenir
que des éléments globaux. Cela est similaire dans les faits à l'utilisation
de la carte <!ELEMENT>
dans une DTD. Dans l'exemple
ci-dessous, nous avons modifié la version originale de po1.xsd
de telle manière que tous les éléments
soient déclarés globalement. Remarquez que nous avons omis dans cet exemple
les attributs elementFormDefault
et
attributeFormDefault
pour
mettre en valeur le fait que leurs valeurs sont sans intérêt dans ce type de
schéma.
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:po="http://www.example.com/PO1" targetNamespace="http://www.example.com/PO1"> <element name="purchaseOrder" type="po:PurchaseOrderType"/> <element name="shipTo" type="po:USAddress"/> <element name="billTo" type="po:USAddress"/> <element name="comment" type="string"/> <element name="name" type="string"/> <element name="street" type="string"/> <complexType name="PurchaseOrderType"> <sequence> <element ref="po:shipTo"/> <element ref="po:billTo"/> <element ref="po:comment" minOccurs="0"/> <!-- etc. --> </sequence> </complexType> <complexType name="USAddress"> <sequence> <element ref="po:name"/> <element ref="po:street"/> <!-- etc. --> </sequence> </complexType> <!-- etc. --> </schema>
Cette version "globale" po1.xsd
validera l'instance po2.xml
qui est
aussi, comme nous l'avons décrit précédemment, valide par rapport à la
version "qualifiée" du schéma, à savoir po1.xsd
. En d'autres termes, les deux approches
permettent de valider le même document qui utiliserait un espace de noms par
défaut. Dans ce sens, elles sont similaires, même si par ailleurs elles sont
vraiment différentes. Plus particulièrement, quand tous les éléments sont
déclarés globalement, il n'est pas possible de tirer partie des possibilités
des noms locaux. Par exemple, vous ne pouvez déclarer qu'un seul élément
global appelé title
. Par contre, vous pouvez déclarer localement
un sous-élément de book
appelé title
ayant un
contenu de type string
comme par exemple un deuxième élément
title
formé de l'énumération des valeurs Mr Mrs
Ms
.
Au chapitre 2 nous avons expliqué les bases de XML Schema en prenant l'exemple d'un schéma sans déclaration de l'espace de noms cible et d'une instance de document sans déclaration d'espace de noms. La question suivante vient donc naturellement à être posée : Quel est l'espace de noms cible de ces exemples et comment est-il référencé ?
Dans le schéma po.xsd
des bons de
commande, aucun espace de noms cible ni préfixe (comme po
:
ci-dessus) n'ont été déclarés qui pourraient nous permettre de faire des
références à des types et des éléments du schéma. La conséquence est que les
définitions et les déclarations de ce schéma, comme par exemple
USAddress
et purchaseOrder
, sont référencées sans
qualification d'espace de noms. En d'autres termes, il n'y un ni préfixe
explicite sur les références ni espace de noms implicite sur la référence par
défaut. Ainsi, l'élément purchaseOrder
est déclaré, dans cet
exemple, en utilisant directement une référence non qualifiée au type
PurchaseOrderType
alors que tous les éléments et les types issus
de XML Schema sont explicitement qualifiés par xsd:
, préfixe
associé à l'espace de noms de XML Schema.
Quand un schéma est conçu sans espace de noms cible, il est fortement
recommandé que tous les éléments et types en provenance de l'espace de noms
de XML Schema soient explicitement qualifiés par un préfixe tel que
xsd:
. La raison en est que, si cette association est faite par
défaut, les références aux types issus de XML Schema pourront ne pas être
distinguées de celles faisant référence aux types définis par
l'utilisateur.
Les déclarations d'éléments d'un schéma n'ayant pas d'espace de noms cible
sont celles utilisées pour valider les éléments non qualifiés de l'instance
de document. Cela étant, elles valident des éléments pour lesquels aucune
qualification d'espace de noms n'est fournie ni directement via un préfixe
explicite ni indirectement via un préfixe par défaut (xmlns:
).
Aussi, pour valider un document XML 1.0 qui, typiquement, n'utilise aucun
espace de noms, vous devez fournir un schéma n'ayant pas d'espace de noms
cible. Comme c'est le cas de la plupart des documents XML 1.0, il y aura
beaucoup de schémas écrits sans espace de noms cibles ; vous devez être sûrs
de donner à votre programme de traitement un schéma qui corresponde au
vocabulaire que vous souhaitez valider.
Le schéma des bons de commande décrit au chapitre 2 était contenu dans un seul et même document et la plupart de ses constructions -- telles que les déclarations d'éléments et les définitions de types -- furent bâties à partir de rien. En réalité, les auteurs de schémas voudront, pour créer de nouveaux types, pouvoir repartir de constructions existantes, réparties dans plusieurs documents. Dans ce chapitre, nous examinons les mécanismes qui le permettent.
Au fur et à mesure que les schémas deviennent plus longs, il est souvent
préférable de les scinder en plusieurs petits documents, pour en faciliter la
maintenance et les conditions d'accès et en augmenter la lisibilité. Pour ces
raisons, nous avons isolé les constructeurs des différents types d'adresses
du schéma po.xsd
et les avons mis dans un
nouveau fichier appelé address.xsd
.
Le schéma ainsi modifié des bons de commande est appelé ipo.xsd
:
<schema targetNamespace="http://www.example.com/IPO" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:ipo="http://www.example.com/IPO"> <annotation> <documentation xml:lang="en"> schéma des bons de commande internationaux pour Exemple.com Copyright 2000 Exemple.com. All rights reserved. </documentation> </annotation> <!-- include address constructs --> <include schemaLocation="http://www.example.com/schemas/address.xsd"/> <element name="purchaseOrder" type="ipo:PurchaseOrderType"/> <element name="comment" type="string"/> <complexType name="PurchaseOrderType"> <sequence> <element name="shipTo" type="ipo:Address"/> <element name="billTo" type="ipo:Address"/> <element ref="ipo:comment" minOccurs="0"/> <element name="items" type="ipo:Items"/> </sequence> <attribute name="orderDate" type="date"/> </complexType> <complexType name="Items"> <sequence> <element name="item" minOccurs="0" maxOccurs="unbounded"> <complexType> <sequence> <element name="productName" type="string"/> <element name="quantity"> <simpleType> <restriction base="positiveInteger"> <maxExclusive value="100"/> </restriction> </simpleType> </element> <element name="USPrice" type="decimal"/> <element ref="ipo:comment" minOccurs="0"/> <element name="shipDate" type="date" minOccurs="0"/> </sequence> <attribute name="partNum" type="ipo:SKU" use="required"/> </complexType> </element> </sequence> </complexType> <simpleType name="SKU"> <restriction base="string"> <pattern value="\d{3}-[A-Z]{2}"/> </restriction> </simpleType> </schema>
Le fichier contenant les constructeurs des différents types d'adresses est :
<schema targetNamespace="http://www.example.com/IPO" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:ipo="http://www.example.com/IPO"> <annotation> <documentation xml:lang="en"> adresses pour schéma des bons de commande internationaux Copyright 2000 Exemple.com. All rights reserved. </documentation> </annotation> <complexType name="Address"> <sequence> <element name="name" type="string"/> <element name="street" type="string"/> <element name="city" type="string"/> </sequence> </complexType> <complexType name="USAddress"> <complexContent> <extension base="ipo:Address"> <sequence> <element name="state" type="ipo:USState"/> <element name="zip" type="positiveInteger"/> </sequence> </extension> </complexContent> </complexType> <complexType name="UKAddress"> <complexContent> <extension base="ipo:Address"> <sequence> <element name="postcode" type="ipo:UKPostcode"/> </sequence> <attribute name="exportCode" type="positiveInteger" fixed="1"/> </extension> </complexContent> </complexType> <!-- other Address dérivations pour plus countries --> <simpleType name="USState"> <restriction base="string"> <enumeration value="AK"/> <enumeration value="AL"/> <enumeration value="AR"/> <!-- et so on ... --> </restriction> </simpleType> <!-- type simple définition pour UKPostcode --> </schema>
Les différents constructeurs du schéma des bons de
commande et des adresses sont maintenant contenus dans deux fichiers séparés,
ipo.xsd
et address.xsd
. Pour inclure les constructions du
deuxième dans le premier, c'est à dire pour les inclure les définitions des
types adresse dans l'espace de noms associé aux bons de commande
internationaux , l'élément include
a été utilisé dans ipo.xsd
:
<include schemaLocation="http://www.example.com/schemas/address.xsd"/>
L'effet de cet élément include
est d'importer les définitions et les déclarations contenues dans le fichier
address.xsd
et de les rendre
totalement intégrées à l'espace de noms cible du schéma des bons de commande
internationaux. L'une des conditions d'utilisation les plus importants de
include
est que l'espace de noms
cible des composants inclus doit être le même que l'espace de noms cible du
schéma les incluant, dans notre cas, il s'agit de
http://www.example.com/IPO
. Importer des définitions et des
déclarations en utilisant le mécanisme include
ajoute effectivement ces
composants à l'espace de noms cible existant. Au chapitre
4.5, nous décrivons un mécanisme complémentaire permettant de modifier
les composants au moment de leur importation.
Dans notre exemple, nous n'avons montré l'inclusion que d'un seul document
et dans un seul document récepteur. En pratique il est possible d'une part
d'inclure plusieurs documents en cumulant plusieurs éléments include
et d'autre part d'imbriquer les
inclusions, les documents inclus pouvant à leur tour inclure d'autres
documents et ainsi de suite. Toutefois, l'imbrication de documents n'est
légale que si la condition de base de l'inclusion est vérifiée : toutes les
parties incluses du schéma doivent avoir le même espace de noms cible.
Les instances de documents conformes au schéma dont les définitions sont
réparties entre plusieurs documents schéma (ndlr : généralement des fichiers
contenant les différentes sous-parties constitutives du schéma final) ont
seulement besoin de référencer le document schéma principal et l'espace de
noms commun ; il est ensuite laissé à la charge du programme de traitement de
savoir collecter toutes les définitions spécifiées dans les différents
documents schéma inclus. Dans l'exemple ci-dessus, une instance de document
ipo.xml
(cf chapitre 4.3) référence seulement l'espace de
noms cible commun, à savoir http://www.example.com/IPO
et (par
conséquence) le seul fichier schéma
http://www.example.com/schemas/ipo.xsd
. Le programme de
traitement doit savoir retrouver le document schéma address.xsd
à partir du fichier schéma de plus
haut niveau.
Au chapitre 5.4, nous décrivons la manière d'utiliser les schémas pour valider un contenu réparti dans plusieurs espaces de noms.
Pour créer nos constructeurs d'adresses, nous avons commencé par créer un
type complexe appelé Address
selon la règle habituelle (cf
address.xsd
) et le type
Address
contient les éléments de base d'une adresse : nom, rue
et ville (une telle définition ne marchera pas pour tous les types d'adresses
du monde entier mais elle sert le propos de notre exemple). A partir de ce
point de départ nous dérivons deux nouveaux types complexes qui contiennent
tous les éléments du type original plus des éléments complémentaires
spécifiques aux adresses américaines et anglaises. La technique que nous
utilisons ici pour dériver ces nouveaux types complexes d'adresses par
extension d'un type existant et la même que celle utilisée au chapitre 2.5.1 excepté que notre type de base
est ici un type complexe d'être un type simple.
Nous définissons les deux nouveaux types complexes, USAddress
et UKAddress
, en utilisant l'élément complexType
. De plus, nous indiquons
que les modèles de contenu des nouveaux types sont eux mêmes de type complexe
en utilisant l'élément complexContent
(c'est à dire que
leurs contenus contiennent des sous-éléments) et nous indiquons qu'il s'agit
d'une extension du type de base Address
en utilisant l'attribut
base
de l'élément extension
.
Quand un type complexe est étendu, son modèle de contenu effectif est
celui du type de base plus celui spécifié dans la dérivation du type. De
plus, les deux modèles de contenu sont traités comme deux enfants d'un groupe
séquentiel. Dans le cas de UKAddress
, le modèle de contenu de
UKAddress
est celui d'Address
augmenté des
déclarations de l'élément postcode
et de celles de l'attribut
exportCode
. Cela revient à définir UKAddress
à
partir de rien comme suit :
<complexType name="UKAddress"> <sequence> <!-- modèle de contenu de Address --> <element name="name" type="string"/> <element name="street" type="string"/> <element name="city" type="string"/> <!-- appended élément declaration --> <element name="postcode" type="ipo:UKPostcode"/> </sequence> <!-- appended attribut declaration --> <attribute name="exportCode" type="positiveInteger" fixed="1"/> </complexType>
Dans le scénario qui nous sert d'exemple, les bons de commande sont
générés en réponse aux ordres des clients qui peuvent avoir des adresses
d'expédition et de facturation différentes. Le bon de commande international,
ipo.xml
ci-dessous, illustre ce cas où
les produits sont expédiés au Royaume-Uni et la facture aux Etats-Unis.
Clairement, il serait mieux que le schéma n'ait pas à lister toutes les
combinaisons possibles des différents cas d'adresses dans les différents pays
du monde et l'idéal serait de pouvoir créer de nouveaux types complexes
d'adresses par simple dérivation du type Address
.
XML Schema nous permet de définir les éléments
billTo
et shipTo
comme étant de type
Address
(cf ipo.xsd
) et
d'utiliser des instances d'adresses internationales à la place des instances
d'Address
. En d'autres termes, une instance de document dont le
contenu est conforme au type UKAddress
sera valide si ce contenu
apparaît dans le document à un endroit où le type Address
était
attendu (en supposant que le contenu de UKAddress
soit lui même
valide). Pour faire marcher cette fonction de XML Schema et pour identifier
exactement quel type dérivé est attendu, le type dérivé doit être identifié
dans une instance de document : cela se fait en utilisant l'attribut xsi:type
qui appartient à l'espace de
noms instance de XML Schema. Dans l'exemple, ipo.xml
, l'utilisation des types dérivés
UKAddress
et USAddress
est identifiée par le biais
des valeurs assignées à l'attribut xsi:type
.
ipo.xml
<?xml version="1.0"?> <ipo:purchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ipo="http://www.example.com/IPO" orderDate="1999-12-01"> <shipTo exportCode="1" xsi:type="ipo:UKAddress"> <name>Helen Zoe</name> <street>47 Eden Street</street> <city>Cambridge</city> <postcode>CB1 1JR</postcode> </shipTo> <billTo xsi:type="ipo:USAddress"> <name>Robert Smith</name> <street>8 Oak Avenue</street> <city>Old Town</city> <state>PA</state> <zip>95819</zip> </billTo> <items> <item partNum="833-AA"> <productName>Lapis necklace</productName> <quantity>1</quantity> <USPrice>99.95</USPrice> <ipo:comment>Want this pour the holidays!</ipo:comment> <shipDate>1999-12-05</shipDate> </item> </items> </ipo:purchaseOrder>
Au chapitre 4.8 nous décrivons comment empêcher cette substitution de type.
En plus de la dérivation par extension, la dérivation de types complexes peut se faire par restriction des modèles de contenu. La restriction de types complexes est conceptuellement la même que celle des types simples et la différence est qu'elle implique l'utilisation de déclarations de types alors qu'en ce qui concerne la restriction des types simples, il s'agit le plus souvent de réduire la fourchette des acceptables du contenu. Un type complexe dérivé par restriction est très similaire à son type de base, excepté que ses déclarations sont plus limitées que les déclarations du type de base. En fait, les valeurs représentées par le nouveau type sont un sous-ensemble des valeurs représentées par le type de base (comme c'est le cas avec la restriction des types simples). En d'autres termes, une application prévue pour l'ensemble des valeurs du type de base s'exécutera sans difficultés sur les valeurs du type restreint.
Par exemple, supposez que nous souhaitions mettre à jour notre définition
de la liste d'items
du bon de commande international de telle
manière qu'elle doive contenir au moins un item
; le
schéma de ipo.xsd
permet pour l'instant à
l'élément items
d'être utilisé sans qu'aucun enfant
item
soit mis à l'intérieur. Pour créer notre nouveau type
ConfirmedItems
, nous le définissons de la manière habituelle
sauf que nous indiquons qu'il est dérivé par restriction à partir du type de
base Items
. Nous fixons alors une valeur plus restrictive du
nombre d'occurrences minimum du sous-élément item
. Remarquez que
les types dérivés par restriction reprennent obligatoirement tous les
composants de leur définition de base :
ConfirmedItems
par restriction à partir de
Items
<complexType name="ConfirmedItems"> <complexContent> <restriction base="ipo:Items"> <sequence> <!-- item élément est different than in Items --> <element name="item" minOccurs="1" maxOccurs="unbounded"> <!-- remainder de définition est same comme Items --> <complexType> <sequence> <element name="productName" type="string"/> <element name="quantity"> <simpleType> <restriction base="positiveInteger"> <maxExclusive value="100"/> </restriction> </simpleType> </element> <element name="USPrice" type="decimal"/> <element ref="ipo:comment" minOccurs="0"/> <element name="shipDate" type="date" minOccurs="0"/> </sequence> <attribute name="partNum" type="ipo:SKU" use="required"/> </complexType> </element> </sequence> </restriction> </complexContent> </complexType>
Ce changement, qui impose désormais aux instances de documents d'avoir au
moins un élément item
par élément items
, est proche
du cas où l'on passe le nombre minimum d'enfants autorisé de 0 à 1. Remarquez
que tous les éléments qui auront le type ConfirmedItems
seront
acceptés comme éléments de type Items
(c'est à dire : là où le
type items
est requis, on peut utiliser un élément de type
ConfirmedItems
).
Pour expliquer encore plus la restriction, nous donnons dans le tableau 3 des exemples de la manière dont les déclarations d'éléments et d'attributs peuvent être restreintes dans des déclarations de type (le tableau montre des syntaxes de déclaration d'élément quoique les trois premiers exemples puissent également s'appliquer à des restrictions de déclarations d'attributs).
Tableau 3. Exemples de restriction | ||
---|---|---|
Base | Restriction | Remarques |
default="1" | initialisation d'une valeur par défaut lorsque aucune était précédemment donnée | |
fixed="100" | initialisation d'une valeur fixée lorsque aucune était précédemment donnée | |
type="string" | spécification d'un type lorsque aucun n'était précédemment donné | |
(minOccurs, maxOccurs) | (minOccurs, maxOccurs) | |
(0, 1) | (0, 0) | exclusion d'un composant optionnel ; cela peut aussi être réalisé en omettant la déclaration du composant de la définition du type réduit |
(0, unbounded) | (0, 0) (0, 37) | |
(1, 9) | (1, 8) (2, 9) (4, 7) (3, 3) | |
(1, unbounded) | (1, 12) (3, unbounded) (6, 6) | |
(1, 1) | - | ne peut pas restreindre plus minOccurs et maxOccurs dans ce cas là |
Le chapitre 4.1 décrit la manière
d'inclure des définitions et des déclarations réparties dans plusieurs
fichiers de schémas mais ayant tous en commun le même espace de noms cible.
Le mécanisme include
permettait
alors d'utiliser "tel-quel" les composants importés de la sorte, en clair,
sans aucune modification. Les chapitres suivant expliquaient les dérivations
de type par extension et par restriction. Le mécanisme redefine
auquel nous allons nous
intéresser dans ce chapitre permet combiner l'inclusion et la restriction de
manière à pouvoir redéfinir des types simples ou complexes, des groupes et
des groupes d'attributs issus de fichiers de schémas externes. Comme pour
include
, le mécanisme redefine
requiert que les composants
externes soient dans le même espace de noms cible que le schéma les
accueillant, cela étant dit, les composants issus de schémas externes sans
espace de noms attribué peuvent également être redéfinis. Dans ce dernier
cas, les composants redéfinis font partie intégrante de l'espace de noms
cible du schéma les accueillant.
Pour illustrer le mécanisme redefine
, nous allons l'utiliser à la
place du mécanisme include
dans
le schéma des bons de commande internationaux, ipo.xsd
et cela dans le but de modifier la
définition du type complexe Address
contenu dans address.xsd
:
redefine
dans le bon de commande
international :<schema targetNamespace="http://www.example.com/IPO" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:ipo="http://www.example.com/IPO"> <!-- bring in address constructs --> <redefine schemaLocation="http://www.example.com/schemas/address.xsd"> <!-- redéfinition de Address --> <complexType name="Address"> <complexContent> <extension base="ipo:Address"> <sequence> <element name="country" type="string"/> </sequence> </extension> </complexContent> </complexType> </redefine> <!-- etc. --> </schema>
L'élément redefine
agit de
manière très voisine à celle de l'élément include
en intégrant toutes les
déclarations et les définitions du fichier address.xsd
. La définition du type complexe
d'Address
utilise la syntaxe d'extension habituelle pour ajouter
l'élément country
à la définition d'Address
.
Toutefois, remarquez que le type de base est aussi Address
. En
dehors de l'élément redefine
,
toute tentative de définition d'un type complexe de même nom (dans le même
espace de noms) que son type de base provoquerait une erreur. Dans le cas
présent, il n'y un pas d'erreur et la définition étendue
d'Address
devient la seule définition d'Address
.
Maintenant que le type Address
a été redéfini, l'extension
s'applique à tous les composants du schéma qui utilisent le type
Address
. Par exemple, address.xsd
contient les définitions de
plusieurs variantes internationales d'adresses dérivées du type
Address
. Ces dérivations reflètent le type redéfini
Address
, comme cela est montré dans l'extrait suivant :
Address
:.... <shipTo exportCode="1" xsi:type="ipo:UKAddress"> <name>Helen Zoe</name> <street>47 Eden Street</street> <city>Cambridge</city> <!-- country was added to Address which est base type de UKAddress --> <country>United Kingdom</country> <!-- postcode was added comme part de UKAddress --> <postcode>CB1 1JR</postcode> </shipTo> ....
Notre exemple a été soigneusement construit de sorte que le type redéfini
Address
ne soit en conflit d'aucune façon avec les types dérivés
de la définition originale du type Address
. Mais remarquez qu'un
conflit pourrait être facilement être créé. Par exemple, si les dérivations
du type adresse internationale avaient étendu Address
en lui
rajoutant l'élément country
, alors la redéfinition du type
Address
consisterait en un rajout d'un élément du même nom à son
modèle de contenu. Or, il est interdit d'avoir deux éléments de même nom (et
de même espace de noms cible) et de type différent dans un même modèle de
contenu : aussi, la tentative de redéfinition du type Address
provoquerait une erreur. En général, redefine
ne vous protège pas de telles
erreurs et doit être utilisé avec précaution.
XML Schema fournit un mécanisme, appelé groupes de
substitution, qui permet aux éléments d'être substitués par d'autres. Plus
précisément, des éléments peuvent être regroupé et déclarés, au niveau du
groupe résultant, substituables par un élément dont on précise le nom. Cet
élément de substitution est appelé élément de tête et doit être un élément
global. Pour illustrer ce propos, nous déclarons deux éléments appelés
customerComment
et shipComment
et on les rattache à
un groupe de substitution dont l'élément de tête est comment
. De
la sorte, customerComment
et shipComment
deviennent
substituables à l'élément comment
, en clair, ils peuvent être
utilisés à n'importe quel endroit où nous pouvons utiliser
comment
. Les éléments d'un groupe de substitution doivent avoir
le même type que l'élément de tête ou être d'un type dérivé du type de
l'élément de tête. Pour déclarer ces deux nouveaux éléments et pour les
rendre substituable à l'élément comment
, nous utilisons la
syntaxe suivante :
<element name="shipComment" type="string" substitutionGroup="ipo:comment"/> <element name="customerComment" type="string" substitutionGroup="ipo:comment"/>
Quand ces déclarations sont rajoutées au schéma des bons de commande
internationaux, shipComment
et customerComment
peuvent venir se substituer à l'élément comment
dans une
instance de document, par exemple :
.... <items> <item partNum="833-AA"> <productName>Lapis necklace</productName> <quantity>1</quantity> <USPrice>99.95</USPrice> <ipo:shipComment> Use gold wrap si possible </ipo:shipComment> <ipo:customerComment> Want this pour the holidays! </ipo:customerComment> <shipDate>1999-12-05</shipDate> </item> </items> ....
Remarquez que lorsqu'une instance de document contient des substitutions
d'éléments dont les types sont dérivés de ceux de leur élément de tête, il
n'est pas nécessaire d'identifier les types dérivés en utilisant le
constructeur xsi:type
que nous
décrivions au chapitre 4.3.
L'existence d'un groupe de substitution n'exige pas d'utiliser un quelconque des éléments de cette classe, ni ne présume de l'utilisation de l'élément tête. Il fournit simplement un mécanisme pour permettre aux éléments d'être interchangeables.
XML Schema fournit un mécanisme pour forcer la
substitution d'un élément ou d'un type en particulier. Quand un élément ou un
type est déclaré comme étant "abstrait", il ne peut pas être utilisé dans une
instance de document. Quand un élément est abstrait, un membre du groupe de
substitution de cet élément doit apparaître dans une instance de document.
Quand la définition type correspondant à un élément est déclarée abstraite,
toutes les instances de cet élément doivent utiliser le constructeur xsi:type
pour faire référence à un type
dérivé qui ne soit pas abstrait.
Dans le groupe de substitution exemple que nous décrivions au chapitre 4.6, il serait pratique d'interdire
spécifiquement l'utilisation de l'élément comment
pour imposer
aux instances l'usage des éléments customerComment
et
shipComment
. Pour déclarer que l'élément comment
est abstrait, nous modifions sa déclaration originale dans le schéma des bons
de commande internationaux, ipo.xsd
,
comme suit :
<element name="comment" type="string" abstrait="true"/>
Avec comment
déclaré comme abstrait, les instances des bons
de commande internationaux sont maintenant valident que si elles contiennent
les éléments customerComment
et shipComment
.
Déclarer un élément comme étant abstrait requiert l'utilisation d'un
groupe de substitution. Déclarer un type comme étant abstrait requiert
simplement l'utilisation, dans les instances de documents, d'un type qui lui
soit dérivé (alors identifié par l'attribut xsi:type
). Considérez la définition de
schéma suivante :
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://cars.example.com/schema" xmlns:target="http://cars.example.com/schema"> <complexType name="Vehicle" abstrait="true"/> <complexType name="Car"> <complexContent> <extension base="target:Vehicle"/> </complexContent> </complexType> <complexType name="Plane"> <complexContent> <extension base="target:Vehicle"/> </complexContent> </complexType> <element name="transport" type="target:Vehicle"/> </schema>
L'élément transport
n'est pas abstrait, en conséquence il
peut apparaître dans les instances de documents. Toutefois, parce que sa
définition de type est abstraite, il ne pourrait pas apparaître dans une
instance de document sans référence à un type dérivé via l'attribut xsi:type
. Cela signifie que l'extrait
suivant n'est pas valide par rapport au schéma :
<transport xmlns="http://cars.example.com/schema"/>
parce que le type de l'élément transport
est abstrait. Par
contre, cet autre fragment est valide :
<transport xmlns="http://cars.example.com/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="Car"/>
parce qu'il utilise un type non-abstrait qui est substituable pour
Vehicle
.
Jusqu'à maintenant, nous avons été capable de dériver de nouveaux types et de les utiliser dans les instances de documents sans aucune restriction. En réalité, les auteurs de schémas voudront parfois contrôler les dérivations de certains types en particulier et l'utilisation de types dérivés dans les instances.
XML Schema fournit un couple de mécanismes qui contrôle la dérivation des
types. L'un de ces mécanismes permet à l'auteur du schéma de spécifier qu'un
type complexe en particulier ne peut faire l'objet de types dérivés, ni (a)
par restriction, ni (b) par extension, ou (c) du tout. Pour illustrer ce
propos, supposons que nous voulions interdire toute dérivation du type
Address
par restriction parce que nous avons l'intention de ne
l'utiliser que comme type de base que pour des types étendus tels que
USAddress
et UKAddress
. Pour interdire ce mode de
dérivation, nous modifions légèrement la définition originale du type
Address
comme suit :
Address
:<complexType name="Address" final="restriction"> <sequence> <element name="name" type="string"/> <element name="street" type="string"/> <element name="city" type="string"/> </sequence> </complexType>
La valeur restriction
de l'attribut
final
empêche les dérivations par
restriction. Empêcher toute dérivation ou n'empêcher que les dérivations par
extension se traduit respectivement par les valeurs #all
et
extension
. De plus, il est possible d'utiliser l'attribut
finalDefault
au niveau de
l'élément schema
permettant
d'imposer un mode de dérivation à toutes les définitions de type et des
déclarations d'éléments du schéma. L'attribut finalDefault
peut prendre les mêmes
valeurs que l'attribut final
.
Un autre mécanisme de dérivation de type permet de
contrôler les facettes autorisées dans la dérivation de nouveaux types
simples. Quand un type simple est défini, l'attribut fixed
peut être appliqué à n'importe
laquelle de ses facettes pour en empêcher la modification lors d'une
dérivation. Par exemple, nous pouvons définir un type simple
Postcode
comme :
<simpleType name="Postcode"> <restriction base="string"> <length value="7" fixed="true"/> </restriction> </simpleType>
Une fois le type simple défini de la sorte, nous pouvons le dériver pour créer un nouveau type de code postal auquel on pourra appliquer une modification d'une facette déclarée non fixée dans la définition de base du type, par exemple :
Postcode
:<simpleType name="UKPostcode"> <restriction base="ipo:Postcode"> <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}"/> </restriction> </simpleType>
Mais il serait impossible de dériver un nouveau type de code postal dans lequel nous tenterions de modifier l'une quelconque des facettes fixées dans la définition de base :
Postcode
:<simpleType name="UKPostcode"> <restriction base="ipo:Postcode"> <pattern value="[A-Z]{2}\d\d[A-Z]{2}"/> <!-- illegal attempt to modify facet fixed in base type --> <length value="6" fixed="true"/> </restriction> </simpleType>
En plus des mécanismes de contrôle des dérivations de
type, XML Schema fournit un mécanisme de contrôle de l'utilisation des
dérivations et groupes de substitution dans les instances de documents. Au chapitre 4.3, nous décrivons comment les types
dérivés, USAddress
et UKAddress
, pouvaient être
utilisés par les éléments shipTo
et billTo
dans les
instances de documents. Ces types dérivés peuvent remplacer le modèle de
contenu fourni par le type Address
parce qu'ils sont dérivés du
type Address
. Toutefois, le remplacement par des types dérivés
peut être contrôlé en utilisant l'attribut block
dans une définition de type. Par
exemple, si nous voulons bloquer l'utilisation de toute dérivation par
restriction à la place du type Address
(peut être pour la même
raison que celle qui nous fait définir Address
avec final="restriction"
), nous pouvons
modifier la définition originale d'Address
comme suit :
Address
dans
l'instance :<complexType name="Address" block="restriction"> <sequence> <element name="name" type="string"/> <element name="street" type="string"/> <element name="city" type="string"/> </sequence> </complexType>
La valeur restriction
de l'attribut
block
empêche que les dérivations
par restriction remplacent Address
dans une instance de
document. Toutefois, cela n'empêcherait pas UKAddress
et
USAddress
de remplacer Address
parce que ces types
étaient dérivés par extension. Empêcher complètement le remplacement par des
types dérivés, ou seulement par ceux dérivés par extension, serait indiqué
respectivement par les valeurs #all
et extension
.
Comme avec final
, il possible
d'utiliser avec l'élément schema
l'attribut blockDefault
qui permet d'appliquer globalement ces contrôles à l'ensemble des définitions
de types et déclarations d'éléments du schéma.
Les applications de dépôt de commande d'achat et de facturation sont
susceptibles de donner lieu à une production de rapports synthétisant le
nombre de produits vendus par région. Un exemple d'un tel rapport, couvrant
la période du quatrième trimestre de l'année 1999, se trouve dans le fichier
4Q99.xml
.
Remarquez que dans ce chapitre nous qualifions les éléments dans le schéma et utilisons des éléments non qualifiés dans les instances, en clair des espaces de noms par défaut (quand cela est possible).
<purchaseReport xmlns="http://www.example.com/Report" period="P3M" periodEnding="1999-12-31"> <regions> <zip code="95819"> <part number="872-AA" quantity="1"/> <part number="926-AA" quantity="1"/> <part number="833-AA" quantity="1"/> <part number="455-BX" quantity="1"/> </zip> <zip code="63143"> <part number="455-BX" quantité="4"/> </zip> </regions> <parts> <part number="872-AA">Lawnmower</part> <part number="926-AA">Baby Monitor</part> <part number="833-AA">Lapis Necklace</part> <part number="455-BX">Sturdy Shelves</part> </parts> </purchaseReport>
Le rapport liste, par nombre et quantité, les pièces facturées dans
différents endroits reconnus par leur code zip et fournit une description de
chaque pièce. En résumant les données de facturation, l'intention du rapport
est claire et les données ne sont pas ambiguës parce qu'un nombre de
contraintes sont à l'oeuvre. Par exemple, chaque code zip apparaît seulement
une seule fois (contrainte d'unicité). De même, la description des pièces
facturées n'apparaît qu'une seule fois même si les pièces ont pu être
facturées à plusieurs codes zip différents (contrainte référentielle),
regardez par exemple la pièce numéro 455-BX
. Dans les chapitres
suivant, nous verrons comment spécifier ces contraintes en utilisant XML
Schema.
<schema targetNamespace="http://www.example.com/Report" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:r="http://www.example.com/Report" xmlns:xipo="http://www.example.com/IPO" elementFormDefault="qualified"> <!-- pour SKU --> <import namespace="http://www.example.com/IPO"/> <annotation> <documentation xml:lang="en"> Report schema for Example.com Copyright 2000 Example.com. All rights reserved. </documentation> </annotation> <element name="purchaseReport"> <complexType> <sequence> <element name="regions" type="r:RegionsType"> <keyref name="dummy2" refer="r:pNumKey"> <selector xpath="r:zip/r:part"/> <field xpath="@number"/> </keyref> </element> <element name="parts" type="r:PartsType"/> </sequence> <attribute name="period" type="duration"/> <attribute name="periodEnding" type="date"/> </complexType> <unique name="dummy1"> <selector xpath="r:regions/r:zip"/> <field xpath="@code"/> </unique> <key name="pNumKey"> <selector xpath="r:parts/r:part"/> <field xpath="@number"/> </key> </element> <complexType name="RegionsType"> <sequence> <element name="zip" maxOccurs="unbounded"> <complexType> <sequence> <element name="part" maxOccurs="unbounded"> <complexType> <complexContent> <restriction base="anyType"> <attribute name="number" type="xipo:SKU"/> <attribute name="quantity" type="positiveInteger"/> </restriction> </complexContent> </complexType> </element> </sequence> <attribute name="code" type="positiveInteger"/> </complexType> </element> </sequence> </complexType> <complexType name="PartsType"> <sequence> <element name="part" maxOccurs="unbounded"> <complexType> <simpleContent> <extension base="string"> <attribute name="number" type="xipo:SKU"/> </extension> </simpleContent> </complexType> </element> </sequence> </complexType> </schema>
XML Schema permet de spécifier la contrainte d'unicité
de toute valeur d'attribut ou d'élément à l'intérieur d'un périmètre défini.
Pour indiquer que la valeur d'un attribut ou d'un élément en particulier est
unique, nous utilisons l'élément unique
. Il permet d'une part de
sélectionner un ensemble d'éléments et ainsi de définir le périmètre
d'applicabilité de la contrainte d'unicité et d'autre part d'identifier le
"champ" de l'attribut ou de l'élément qui doit être unique à l'intérieur du
périmètre défini. Dans le cas du schéma de notre rapport, report.xsd
, l'attribut xpath
de l'élément selector
contient une expression XPath
qui est regions/zip
qui retourne la liste de tous les éléments
zip
d'une instance du rapport. De même, l'attribut xpath
de l'élément field
contient une seconde expression XPath,
@code
, qui spécifie que les valeurs de l'attribut
code
des éléments retournés doivent être uniques. Remarquez
comment les expressions XPath limitent la portée de ce qui doit être unique.
En effet, le rapport peut contenir un autre attribut code
mais
cette valeur ne sera pas prise en compte dans le calcul d'unicité puisqu'elle
réside à l'extérieur du périmètre défini par la première expressions XPath.
Remarquez aussi que les expressions XPath que vous pouvez utiliser dans
l'attribut xpath
sont limitées à
un sous-ensemble
de l'ensemble du langage XPath défini dans XML Path Language
1.0. (remarque de traduction : une version française de cette
recommandation existe également).
Nous pouvons aussi indiquer des combinaisons de champs qui doivent être
uniques. Pour illustrer ce propos, supposez que nous pouvons relâcher la
contrainte d'unicité sur les codes zip bien que nous souhaitions conserver la
contrainte d'unicité des produits par code zip. Nous pourrions atteindre cet
objectif en spécifiant qu'un couple formé du code zip et du numéro de produit
doit être unique. D'après le document rapport 4Q99.xml
, les valeurs combinées du code zip et du
numéro de produit seraient : {95819 872-AA
}, {95819
926-AA
}, {95819 833-AA
}, {95819 455-BX
}, et
{63143 455-BX
}. En clair, ces couples ne font pas la distinction
entre les combinaisons des codes zip et des numéros d'article obtenus à
partir d'une ou plusieurs listes de codes zip spécifiés et la présence d'un
produit vendu plus d'une fois pour un même code zip serait listée de manière
non équivoque (c'est à dire plusieurs fois). En d'autres termes, un programme
de traitement du schéma serait capable de détecter les violations de la
contrainte d'unicité.
Pour définir des combinaisons de valeurs, nous ajoutons simplement des
éléments field
pour identifier
toutes les valeurs impliquées. Aussi, pour ajouter le numéro d'article sans
doublon à notre définition actuelle, nous ajoutons un nouvel élément field
dont la valeur de l'attribut xpath
qui est part/@number
.
La définition résultante sélectionne les élément zip
enfants des
éléments regions
différents pas leurs code
puis les
éléments part
enfants des éléments zip
différents
par la valeur de leur attribut number
:
<unique name="dummy1"> <selector xpath="r:regions/r:zip"/> <field xpath="@code"/> <field xpath="r:part/@number"/> </unique>
Dans le rapport des ventes trimestrielles de 1999, la
description de chaque pièce facturée n'apparaît qu'une fois. Nous pourrions
renforcer cette contrainte en utilisant l'élément unique
mais nous souhaitons aussi garantir
la présence d'une description de pièce pour chaque couple pièce-quantité
listé sous un code zip. Nous renforçons la contrainte en utilisant les
éléments key
et keyref
. Le schéma du rapport, report.xsd
, montre que les constructions
key
et keyref
sont appliquées en utilisant presque
la même syntaxe que unique
.
L'élément clé s'applique à la valeur de l'attribut number
des
éléments part
, enfants de l'élément parts
. Le fait
de déclarer que l'attribut number
est une clé signifie que sa
valeur doit être unique et ne peut pas être initialisée à nil
(c'est à dire qu'elle est forcément renseignée) et le nom associé à la clé,
pNumKey
, la rend référençable de n'importe où.
Pour garantir que les couples pièce-quantité font référence à des
descriptions de pièces, nous spécifions que l'attribut number
(<field>@number</field>
) est une référence
(keyref
) à pNumKey
qui est une clé
(key
). Ainsi faite, la déclaration de number
signifie que lorsque cet attribut est utilisé dans une instance de document,
sa valeur doit être égale à celle d'un pNumKey
. La valeur de
l'attribut clé (pNumKey
) doit être unique mais elle peut être
référencée par plusieurs attributs de type keyref comme par exemple
number
. (note de la traduction française : le mécanisme décrit
ici ne garantit pas que la référence faite à la description soit la
bonne).
Comme vous pouvez vous en douter par analogie avec l'élément unique
, il est possible de définir des
combinaisons des valeurs de key
et
keyref
. En utilisant ce mécanisme,
nous pourrions assez facilement aller plus loin en exigeant que les numéros
d'articles soient égaux et en définissant une combinaison de valeurs qui
doivent être égales. Les valeurs dont on parle peuvent être des combinaisons
de plusieurs types de valeurs (string
,
integer
, date
, etc.) à condition que l'ordre et le type des
références de l'élément field
soient identiques dans les deux définitions de key
et de keyref
.
XML 1.0 fournit
un mécanisme de contrôle d'unicité via les attributs de type ID, IDREF et
IDREFS. Il existe aussi dans XML Schema au travers des types simples ID
, IDREF
, et
IDREFS
qui permettent de déclarer des
attributs de type XML 1.0. Mais XML Schema introduit des mécanismes
complémentaires plus souples et plus puissants. Par exemple, les règles
d'unicité peuvent être appliquée à tout contenu d'élément ou d'attribut,
quelqu'en soit leurs types. A l'inverse, ID est un type de la déclaration
attribute
et ne peut s'appliquer aux attributs (ndlr : la
phrase semble être une erreur mais c'est écrit tel quel dans le texte
original anglais), aux éléments ou à leurs contenus. XML Schema permet
de spécifier le périmètre de confinement de l'unicité alors que celui d'un ID
est toujours le document dans sa totalité. Finalement, XML Schema permet de
créer des types key
et keyref
en relation avec le contenu des
éléments et des attributs alors que ID ne propose pas ces facilités.
Le schéma du rapport, report.xsd
, fait appel au type simple appelé
xipo:SKU
, défini dans un autre schéma et dans un autre espace de
noms cible. Nous rappelons que nous avons utilisé include
pour que le schéma ipo.xsd
intègre les définitions et des
déclarations de address.xsd
. Ici,
nous ne pouvons pas utiliser include
puisque include
ne s'applique qu'à des schémas
externes de même espace de noms cible. Il s'ensuit que l'élément include
ne permet pas d'identifier des
espaces de noms cibles spécifiques (bien que ce mécanisme ait besoin d'un
schemaLocation
). Le
mécanisme d'import que nous décrivons dans ce chapitre est important car il
permet aux composants de schémas issus de différents espaces de noms cibles
d'être utilisés ensemble. Cela offre la possibilité de valider des contenus
d'instances de documents écrites avec des composants définis à travers
plusieurs espaces de noms.
Pour importer le type SKU
et l'utiliser
dans le schéma du rapport, nous déclarons l'espace de noms dans lequel
SKU
est défini et l'associons à un préfixe à utiliser dans le
schéma du rapport. Concrètement, nous utilisons l'élément import
pour identifier l'espace de noms
cible de SKU
, http://www.example.com/IPO
et nous
l'associons au préfixe xipo
au moyen d'une déclaration standard
d'espace de noms. Le type simple SKU
, défini dans l'espace de
noms http://www.example.com/IPO
, peut ensuite être référencé
comme xipo:SKU
dans toutes les définitions et déclarations du
schéma du rapport.
Dans notre exemple, nous importons un type simple à partir d'un espace de
noms externe et l'utilisons dans des déclarations d'attributs. XML Schema
permet d'importer plusieurs composants d'un schéma, issus de plusieurs
espaces de noms différents qui peuvent ensuite être référencés à partir des
définitions et des déclarations. Par exemple dans report.xsd
nous pourrions réutiliser l'élément
comment
déclaré dans ipo.xsd
en le référençant à l'aide de la déclaration suivante :
<element ref="xipo:comment"/>
Remarquez toutefois que nous ne pouvons pas réutiliser l'élément
shipTo
de po.xsd
, et le cas
suivant est illégal parce que seuls les composants d'un schéma
global peuvent être importés :
<element ref="xipo:shipTo"/>
Dans ipo.xsd
, l'élément
comment
est déclaré globalement, en d'autres termes il est
déclaré comme un élément directement fils de l'élément racine schema
. Par contre, shipTo
est
déclaré localement, en clair il est déclaré à l'intérieur une définition de
type complexe, en l'occurrence le type PurchaseOrderType
.
Les types peuvent aussi être importés et être utilisés comme types de base
pour dériver de nouveaux types. Seuls les types complexes nommés peuvent être
importés ; les types locaux définis anonymement ne peuvent pas être importés.
Supposez que nous voulions inclure dans nos rapports le nom d'un analyste et
ses coordonnées pour le contacter. Nous pouvons réutiliser le type complexe
(défini globalement) USAddress
de address.xsd
et l'étendre afin de définir un
nouveau type appelé Analyst
qui contiendra les deux nouveaux
éléments phone
et email
:
Analyst
par extension de
USAddress
<complexType name="Analyst"> <complexContent> <extension base="xipo:USAddress"> <sequence> <element name="phone" type="string"/> <element name="email" type="string"/> </sequence> </extension> </complexContent> </complexType>
Avec ce nouveau type, nous pouvons déclarer un élément appelé
analyst
dans la déclaration de l'élément
purchaseReport
(ces déclarations ne sont pas données en exemple)
dans le schéma du rapport. L'instance de document suivante sera conforme au
schéma ainsi modifié :
Analyst
<purchaseReport xmlns="http://www.example.com/Report" period="P3M" periodEnding="1999-12-31"> <!-- regions et parts éléments omitted --> <analyst> <name>Wendy Uhro</name> <street>10 Corporate Towers</street> <city>San Jose</city> <state>CA</state> <zip>95113</zip> <phone>408-271-3366</phone> <email>uhro@exemple.com</email> </analyst> </purchaseReport>
Quand les composants d'un schéma proviennent de plusieurs espaces de noms,
chacun doit être identifié par un élément import
distinct. Les éléments import
eux-mêmes doivent apparaître comme
étant les premiers enfants de l'élément schema
. En plus, chaque espace de noms doit
être associé à un préfixe utilisé pour qualifier les références aux
composants des schéma importés. Finalement, les éléments import
peuvent recevoir l'attribut schemaLocation
pour donner la
localisation des ressources associées aux espaces de noms. Cet attribut est
détaillé plus loin.
Au fur et à mesure que XML schemas deviendra plus largement utilisé, les auteurs de schémas voudront créer des types simples et complexes qui puissent être partagés et utilisés entre différents schemas. XML Schemas fournit déjà des types qui jouent ce rôle, en particulier, les types décrits dans l'annexe des types simples et dans la présentation des bibliothèques de types.
Les auteurs de schémas voudront, à n'en pas douter, créer leurs propres
bibliothèques de types pour représenter par exemple des monnaies, des unités
de mesure, des listes d'adresses professionnelles etc. Chaque bibliothèque
peut consister en un schéma contenant une ou plusieurs définitions, par
exemple, celle d'un type currency
:
currency
dans une bibliothèque de types :<schema targetNamespace="http://www.example.com/Currency" xmlns:c="http://www.example.com/Currency" xmlns="http://www.w3.org/2001/XMLSchema"> <annotation> <documentation xml:lang="en"> Definition of Currency type based on ISO 4217 </documentation> </annotation> <complexType name="Currency"> <simpleContent> <extension base="decimal"> <attribute name="name"> <simpleType> <restriction base="string"> <enumeration value="AED"> <annotation> <documentation xml:lang="en"> United Arab Emirates: Dirham (1 Dirham = 100 Fils) </documentation> </annotation> </enumeration> <enumeration value="AFA"> <annotation> <documentation xml:lang="en"> Afghanistan: Afghani (1 Afghani = 100 Puls) </documentation> </annotation> </enumeration> <enumeration value="ALL"> <annotation> <documentation xml:lang="en"> Albania, Lek (1 Lek = 100 Qindarka) </documentation> </annotation> </enumeration> <!-- et other currencies --> </restriction> </simpleType> </attribute> </extension> </simpleContent> </complexType> </schema>
Exemple d'un élément apparaissant dans une instance et ayant ce type :
<convertFrom name="AFA">199.37</convertFrom>
Une fois le type currency
défini, il peut être disponible
pour une réutilisation dans d'autres schémas via le mécanisme import
qui vient juste d'être décrit.
any
Dans les chapitres précédents nous avons vu plusieurs mécanismes permettant d'étendre les modèles de contenu des types complexes. Par exemple, un modèle de contenu mixte peut contenir un mélange de caractères de données et d'éléments mais un modèle de contenu peut également contenir des éléments dont les types sont issus d'espaces de noms externes. Ces mécanismes offrent respectivement des contraintes très lâches ou très strictes. Le but de ce chapitre est de décrire un mécanisme souple qui permette aux modèles de contenu d'être étendus par n'importe quel élément et attribut des espaces de noms spécifiés.
Pour illustrer ce propos, considérez une version du rapport trimestriel
4Q99html.xml
, dans laquelle nous
avons embarqué une représentation HTML des données XML des pièces. Le contenu
HTML apparaît comme contenu de l'élément htmlExemple
et l'espace
de noms par défaut est changé pour l'élément HTML de plus haut niveau
(l'élément table
) de telle sorte que tous les éléments HTML
appartiennent à l'espace de noms de HTML,
http://www.w3.org/1999/xhtml
:
<purchaseReport xmlns="http://www.example.com/Report" period="P3M" periodEnding="1999-12-31"> <regions> <!-- part sales listed par zip code, data from 4Q99.xml --> </regions> <parts> <!-- part descriptions from 4Q99.xml --> </parts> <htmlExemple> <table xmlns="http://www.w3.org/1999/xhtml" border="0" width="100%"> <tr> <th align="left">Zip Code</th> <th align="left">Part nombre</th> <th align="left">quantité</th> </tr> <tr><td>95819</td><td> </td><td> </td></tr> <tr><td> </td><td>872-AA</td><td>1</td></tr> <tr><td> </td><td>926-AA</td><td>1</td></tr> <tr><td> </td><td>833-AA</td><td>1</td></tr> <tr><td> </td><td>455-BX</td><td>1</td></tr> <tr><td>63143</td><td> </td><td> </td></tr> <tr><td> </td><td>455-BX</td><td>4</td></tr> </table> </htmlExemple> </purchaseReport>
Pour autoriser l'apparition des balises HTML dans les
instances de rapports nous en modifions le schéma en déclarant un nouvel
élément htmlExemple
dont le contenu est défini par l'élément
any
. En général, un élément any
spécifie que tout fragment XML bien formé
est autorisé comme modèle de contenu du type. Dans l'exemple, nous demandons
au XML d'appartenir à l'espace de noms
http://www.w3.org/1999/xhtml
, en d'autres termes, il doit être
HTML. L'exemple requiert via les valeurs de minOccurs
et maxOccurs
, qu'il y ait au moins un
élément de cet espace de noms.
purchaseReport
pour
autoriser l'usage de HTML dans l'instance :<element name="purchaseReport"> <complexType> <sequence> <element name="regions" type="r:RegionsType"/> <element name="parts" type="r:PartsType"/> <element name="htmlExemple"> <complexType> <sequence> <any namespace="http://www.w3.org/1999/xhtml" minOccurs="1" maxOccurs="unbounded" processContents="skip"/> </sequence> </complexType> </element> </sequence> <attribute name="period" type="duration"/> <attribute name="periodEnding" type="date"/> </complexType> </element>
La modification permet aux fragments XML bien formés
de l'espace de noms http://www.w3.org/1999/xhtml
d'apparaître à
l'intérieur de l'élément htmlExemple
. Par conséquent 4Q99html.xml
est admis parce qu'il contient
un élément qui (avec ses enfants) est bien formé, l'élément apparaît à
l'intérieur de l'élément approprié (htmlExemple
) et l'instance
de document affirme que l'élément et son contenu appartiennent à l'espace de
noms requis. Toutefois, le fragment HTML qui s'y trouve peut ne pas être
valide parce que rien dans l'instance 4Q99html.xml
ne peut intrinsèquement le
garantir. Si cette garantie est nécessaire, la valeur de l'attribut processContents
doit être
initialisé à strict
(la valeur par défaut). Dans ce cas, le
programme de traitement de l'instance XML est obligé d'obtenir le schéma
associé à l'espace de noms requis (http://www.w3.org/1999/xhtml
)
et de valider le contenu HTML apparaissant à l'intérieur de l'élément
htmlExemple
.
Dans l'exemple suivant, nous définissons un type
text
similaire au type text
défini dans la
présentation de la bibliothèque de
types de XML Schema (cf le chapitre 5.4.1) qui
convient pour du texte internationalisé lisible par un oeil humain. Le
nouveau type text
permet d'avoir un mélange d'éléments et de
caractères de données sans restriction, de n'importe quel espace de noms,
comme par exemple des annotations Ruby, parallèlement à l'utilisation de
l'attribut optionnel xml:lang
. La valeur lax
de
l'attribut processContents
dit au programme
de traitement de l'instance XML de valider le contenu de l'élément sur la
base d'un "peut-le-faire" : il validera les éléments et les attributs pour
lesquels il peut obtenir l'information de schéma, mais il ne signalera pas
d'erreur pour ceux dont il ne peut pas obtenir une quelconque information de
schéma.
text
:<xsd:complexType name="text"> <xsd:complexContent mixed="true"> <xsd:restriction base="xsd:anyType"> <xsd:sequence> <xsd:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> <xsd:attribute ref="xml:lang"/> </xsd:restriction> </xsd:complexContent> </xsd:complexType>
Les espaces de noms peuvent être utilisés pour
permettre et interdire le contenu de l'élément de différentes manières en
fonction de la valeur de l'attribut namespace
, comme cela est montré dans
le tableau 4 :
En plus de l'élément any
qui autorise un contenu d'élément en
fonction des espaces de noms, il y a un élément correspondant anyAttribute
qui autorise les
attributs d'apparaître dans des éléments. Par exemple, nous pouvons permettre
à tout attribut HTML d'apparaître dans l'élément htmlExemple
en
rajoutant anyAttribute
à sa
déclaration :
htmlExemple
pour autoriser
l'utilisation des attributs HTML :<element name="htmlExemple"> <complexType> <sequence> <any namespace="http://www.w3.org/1999/xhtml" minOccurs="1" maxOccurs="unbounded" processContents="skip"/> </sequence> <anyAttribute namespace="http://www.w3.org/1999/xhtml"/> </complexType> </element>
Cette déclaration permet à un attribut HTML, disons href
,
d'apparaître dans l'élélment htmlExemple
. Par exemple :
htmlExemple
:.... <htmlExemple xmlns:h="http://www.w3.org/1999/xhtml" h:href="http://www.example.com/reports/4Q99.html"> <!-- HTML markup here --> </htmlExemple> ....
L'attribut namespace
de
l'élément anyAttribute
peut
être prendre n'importe laquelle des valeurs listée pour l'élément any
dans le tableau 4
et anyAttribute
peut être
qualifié par l'attribut processContents
. En opposition à
un élément any
, l'élément anyAttribute
ne peut pas contraindre
le nombre d'attributs qui peut apparaître dans un élément.
schemaLocation
XML Schema utilise les attributs schemaLocation
et xsi:schemaLocation
dans trois
cas de figures.
1. dans une instance de document, l'attribut xsi:schemaLocation
fournit
une indication de l'auteur au programme de traitement concernant
l'emplacement des documents schéma. L'auteur garantit que les schéma
mentionnés sont corrects pour contrôler, espace de noms par espace de noms,
la validité du contenu du document. Par exemple, nous pouvons indiquer
l'emplacement du schéma du rapport à un programme de traitement du rapport
trimestriel :
schemaLocation
dans le rapport
trimestriel, 4Q99html.xml
<purchaseReport xmlns="http://www.example.com/Report" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com/Report http://www.example.com/Report.xsd" period="P3M" periodEnding="1999-12-31"> <!-- etc. --> </purchaseReport>
L'attribut schemaLocation
contient des pairs
de valeurs : le premier membre de chaque paire est l'espace de noms dont le
second membre est l'emplacement recommandé où trouver le schéma approprié. La
présence de ces recommandations n'impose au programme de traitement ni qu'il
puisse réellement accéder au schémas mentionnés ni qu'il les exploite. Le
programme de traitement est libre d'utiliser d'autres schémas obtenus par
tout moyen à sa convenance ou de ne pas utiliser de schéma du tout.
Un schéma n'est pas obligé d'avoir un espace de noms (cf chapitre 3.4). L'attribut noNamespaceSchemaLocation
sert alors à fournir aux programmes de traitement des informations sur les
emplacements des schémas qui n'ont pas d'espace de noms cible.
2. Dans un schéma, l'élément include
a un attribut obligatoire,
schemaLocation
, dont la
valeur est une URI de référence qui doit identifier un document schéma.
L'effet est de construire un schéma final effectif en fusionnant les
déclarations et les définitions des schémas appelant et appelé. Par exemple,
au chapitre 4, les définitions des types
Address
, USAddress
, UKAddress
,
USState
(complétées de leurs déclarations d'attributs et
d'éléments locaux respectives) du schéma address.xsd
ont été ajoutées aux déclarations
d'éléments de purchaseOrder
et comment
, et aux
définitions de PurchaseOrderType
, Items
et
SKU
(aussi complétées de leurs déclarations d'attributs et
d'éléments locaux) de ipo.xsd
pour former
un seul schéma.
3. Dans un schéma, l'élément import
a aussi des attributs optionnels
namespace
et schemaLocation
. L'attribut
schemaLocation
a la même
signification que l'attribut xsi:schemaLocation
expliqué
en (1). Plus particulièrement, il fournit une recommandation de l'auteur
quant à l'emplacement du document schéma dont l'auteur garantit qu'il fournit
les composants requis pour l'espace de noms identifié par l'attribut namespace
. Pour importer des
composants qui sont dans aucun espace de noms cible, l'élément import
, avec ou sans attribut schemaLocation
, sera utilisé sans
attribut namespace
. Les
références aux composants importés de la sorte sont non qualifiées.
Remarquez que l'attribut schemaLocation
ne fournit qu'un
conseil et certains programmes de traitements et applications auront raison
de ne pas exploiter cette donnée. Par exemple, un éditeur HTML peut avoir un
schéma HTML intégré.
une instance de document peut être contrôlée vis à vis d'un schéma pour vérifier si les règles qui y sont spécifiées sont appliquées dans l'instance. Ce traitement fait classiquement deux choses, (1) il contrôle la conformité aux règles, processus appelé validation du schéma et (2) il ajoute des informations supplémentaires qui ne sont pas présentes originellement dans l'instance, comme par exemple des types et des valeurs par défaut, et qui sont appelées informations de contribution.
L'auteur d'une instance de document, un bon de commande par exemple, peut
réclamer dans l'instance elle-même, qu'elle se conforme aux règles d'un
schéma en particulier. L'auteur le fait en utilisant l'attribut schemaLocation
discuté ci-dessus.
Mais indépendamment de la présence ou non de l'attribut schemaLocation
, une application
est libre de traiter un document au regard de n'importe quel schéma. Par
exemple, une application de gestion des achats peut avoir comme politique
d'utiliser toujours le même schéma de bon de commande, cela indépendamment de
toute valeur de l'attribut schemaLocation
.
Le contrôle de conformité peut être représenté comme procédant étape par étape, contrôlant en premier que l'élément racine du instance de document a les bons contenus, puis contrôlant que chaque sous-élément soit conforme à sa description dans un schéma et ainsi de suite jusqu'à ce que tout le document soit vérifié. Les programmes de traitement doivent rapporter ce que le contrôle a permis de vérifier.
Pour contrôler la conformité d'un élément, le programme de traitement
commence par identifier la déclaration de l'élément dans un schéma puis
contrôle que l'attribut targetNamespace
du schéma
corresponde à l'URI de l'espace de noms de l'élément. Une autre solution
serait de déterminer que le schéma n'a pas d'attribut targetNamespace
et que l'élément
instancié n'est pas qualifié par un préfixe d'espace de noms.
En supposant que les espaces de noms correspondent, le programme de
traitement examine ensuite le type de l'élément, soit tel qu'il est donné par
la déclaration qui se trouve dans le schéma soit via la présence d'un
attribut xsi:type
dans
l'instance. Dans le dernier cas, le type instancié doit être une substitution
autorisée du type donné dans le schéma ; ce qui est autorisé dépend de
l'attribut block
de la
déclaration de l'élément. Arrivé à ce stade, les valeurs par défaut et
d'autres informations de contribution sont appliquées.
Ensuite, le programme de traitement contrôle les attributs et les contenus
immédiats de l'élément, les comparant avec les attributs et contenus
autorisés par le type de l'élément. Par exemple, considérons un élément
shipTo
identique à celui du chapitre
2.1, le programme de traitement contrôle ce qui est autorisé par le
modèle Address
, type de l'élément shipTo
.
Si l'élément a un type simple, le programme de traitement vérifie que l'élément n'a pas d'attribut et ne contient pas lui même d'autres éléments et que les caractères qu'il contient correspondent au règles du type simple concerné. Cela implique parfois de contrôler la séquence de caractères vis à vis d'expressions régulières ou d'énumérations et aussi parfois de contrôler que la séquence de caractères représente une valeur autorisée de la fourchette de valeurs spécifiée.
Si l'élément a un type complexe, alors le programme de traitement contrôle
que les attributs obligatoires sont présents, que leurs valeurs sont
conformes aux exigences de leurs types. Il contrôle aussi que tous les
sous-éléments obligatoires sont présents et que la séquence des sous-éléments
(et tout contenu mixte) est conforme au modèle de contenu déclaré du type
complexe concerné. En ce qui concerne les sous-éléments, les schémas peuvent
soit exiger qu'il y ait une correspondance exacte des noms, soit autoriser la
substitution par un élément équivalent ou par tout élément autorisé suite à
l'utilisation de la particule 'any
'.
A moins qu'un schéma n'indique le contraire (comme cela est possible avec
la particule 'any
'), le contrôle de conformité rentre ensuite
dans les niveaux plus bas en s'intéressant aux sous-éléments, l'un après
l'autre, répétant pour chacun l'opération décrite ci-dessus.
Beaucoup de personnes ont contribué par des idées, de la matière et des remarques à l'élaboration de ce document, ce qui en a considérablement amélioré la qualité. En particulier, l'éditeur met en exergue les apports de David Beech, Paul Biron, Don Box, Allen Brown, David Cleary, Dan Connolly, Roger Costello, Martin Dürst, Martin Gudgin, Dave Hollander, Joe Kesselman, John McCarthy, Andrew Layman, Eve Maler, Ashok Malhotra, Noah Mendelsohn, Michael Sperberg-McQueen, Henry Thompson, Misha Wolf, et Priscilla Walmsley pour la validation des exemples cités.
Les valeurs légales de chaque type simple peuvent être contraintes par l'application d'une ou plusieurs facettes. Les tableaux B1.a et B1.b listent tous les types simples pré-définis de XML Schema et les facettes applicables à chacun. Les noms des types simples et les facettes sont liées entre les tableaux et leurs descriptions correspondantes dans XML Schema Partie 2 : types de données
Tableau B1.a. Types simples et facettes applicables | ||||||
---|---|---|---|---|---|---|
Types simples | Facettes | |||||
length | minLength | maxLength | pattern | enumeration | whiteSpace | |
string | y | y | y | y | y | y |
normalizedString | y | y | y | y | y | y |
token | y | y | y | y | y | y |
byte | y | y | y | |||
unsignedByte | y | y | y | |||
base64Binary | y | y | y | y | y | y |
hexBinary | y | y | y | y | y | y |
integer | y | y | y | |||
positiveInteger | y | y | y | |||
negativeInteger | y | y | y | |||
nonNegativeInteger | y | y | y | |||
nonPositiveInteger | y | y | y | |||
int | y | y | y | |||
unsignedInt | y | y | y | |||
long | y | y | y | |||
unsignedLong | y | y | y | |||
short | y | y | y | |||
unsignedShort | y | y | y | |||
decimal | y | y | y | |||
float | y | y | y | |||
double | y | y | y | |||
boolean | y | y | ||||
time | y | y | y | |||
dateTime | y | y | y | |||
duration | y | y | y | |||
date | y | y | y | |||
gMonth | y | y | y | |||
gYear | y | y | y | |||
gYearMonth | y | y | y | |||
gDay | y | y | y | |||
gMonthDay | y | y | y | |||
Name | y | y | y | y | y | y |
QName | y | y | y | y | y | y |
NCName | y | y | y | y | y | y |
anyURI | y | y | y | y | y | y |
language | y | y | y | y | y | y |
ID | y | y | y | y | y | y |
IDREF | y | y | y | y | y | y |
IDREFS | y | y | y | y | y | |
ENTITY | y | y | y | y | y | y |
ENTITIES | y | y | y | y | y | |
NOTATION | y | y | y | y | y | y |
NMTOKEN | y | y | y | y | y | y |
NMTOKENS | y | y | y | y | y |
Les facettes listées dans le tableau B1.b ne s'appliquent qu'à des types simples ordonnés. Comme cela n'est pas applicable à tous les types simples, ce deuxième tableau ne contient qu'un sous-ensemble de la liste des types simples.
Tableau B1.b. Types simples et facettes applicables | ||||||
---|---|---|---|---|---|---|
Simple Types | Facets | |||||
max Inclusive |
max Exclusive |
min Inclusive |
min Exclusive |
totalDigits | fractionDigits | |
byte | y | y | y | y | y | y |
unsignedByte | y | y | y | y | y | y |
integer | y | y | y | y | y | y |
positiveInteger | y | y | y | y | y | y |
negativeInteger | y | y | y | y | y | y |
nonNegativeInteger | y | y | y | y | y | y |
nonPositiveInteger | y | y | y | y | y | y |
int | y | y | y | y | y | y |
unsignedInt | y | y | y | y | y | y |
long | y | y | y | y | y | y |
unsignedLong | y | y | y | y | y | y |
short | y | y | y | y | y | y |
unsignedShort | y | y | y | y | y | y |
decimal | y | y | y | y | y | y |
float | y | y | y | y | ||
double | y | y | y | y | ||
time | y | y | y | y | ||
dateTime | y | y | y | y | ||
duration | y | y | y | y | ||
date | y | y | y | y | ||
gMonth | y | y | y | y | ||
gYear | y | y | y | y | ||
gYearMonth | y | y | y | y | ||
gDay | y | y | y | y | ||
gMonthDay | y | y | y | y |
XML 1.0 fournit différents types d'entités qui sont des fragments de contenu étiquetés qui peuvent être utilisé tant pour l'écriture de DTD (les entités paramètre) que les instances de documents. Au chapitre 2.7, nous expliquons comment des groupes nommés offrent une fonctionnalité voisine de celle offerte par les entités paramètres. Dans ce chapitre nous montrons comment les entités peuvent être déclarées dans les instances de documents et comment les équivalents fonctionnels des entités peuvent être déclarés dans les schémas.
Supposez que nous voulions déclarer et utiliser un entité dans une instance de document et que le document soit aussi contraint par un schéma. Par exemple :
<?xml version="1.0" ?> <!DOCTYPE PurchaseOrder [ <!ENTITY eacute "é"> ]> <purchaseOrder xmlns="http://www.example.com/PO1" orderDate="1999-10-20> <!-- etc. --> <city>Montréal</city> <!-- etc. --> </purchaseOrder>
Ici, nous déclarons une entité appelée eacute
dans un
sous-ensemble local au document de la DTD (c'est à dire dans le prologue du
document) et nous référençons ensuite cette entité dans le contenu de
l'élément city
. Remarquez que, quand cette instance de document
sera traitée, l'entité sera dé-référencée (c'est à dire résolue) avant que la
validation de la conformité de l'instance par rapport au schéma ait lieu. En
d'autres termes, un programme de conformité déterminera la validité de
l'élément city
en utilisant Montréal
comme contenu
de l'élément.
Nous pouvons aboutir à une approche similaire sans toutefois être identique en déclarant dans le schéma un élément dont le contenu sera défini de manière appropriée comme suit :
<xsd:element name="eacute" type="xsd:token" fixed="é"/>
Cet élément peut être utilisé dans une instance de document de la manière suivante :
<?xml version="1.0" ?> <purchaseOrder xmlns="http://www.example.com/PO1" xmlns:c="http://www.example.com/characterLes éléments" orderDate="1999-10-20> <!-- etc. --> <city>Montr<c:eacute/>al</city> <!-- etc. --> </purchaseOrder>
Dans ce cas, un programme de validation traitera deux éléments, un élément
city
et un élément eacute
pour lequel le programme
de traitement fournira le caractère é
. Remarquez que le rajout
de cet élément compliquera les applications de recherche de chaînes de
caractères ; les deux formes du nom "Montréal" données dans les deux exemples
ci-dessus ne se trouveront pas mutuellement en utilisant les techniques
standard de comparaison de chaînes de caractères.
La facette pattern
de XML
Schema utilise le langage des expressions régulières qui supporte Unicode.
Il est totalement décrit dans XML Schema
tome 2. Le langage est similaire à celui utilisé dans le langage de
programmation Perl, bien que les expressions soient mises en
correspondance avec une représentation lexicale complète plutôt qu'au travers
d'une représentation du niveau utilisateur comme c'est le cas par exemple
avec les notions de ligne et de paragraphe. Pour cette raison, le langage
d'expression ne contient pas les métacaractères ^ et $, bien que ^ soit
utilisé pour exprimer les exclusions, par exemple [^0-9]x.
Table D1. Exemples d'expressions régulières | |
---|---|
Expression | Exemples de correspondance(s) |
chapitre \d |
chapitre 0 , chapitre 1 , chapitre
2 .... |
chapitre\s\d |
chapitre suivi par un seul caractère espace blanc (espace, tabulation, retour à la ligne, etc.) suivi par un seul chiffre |
chapitre\s\w |
chapitre suivi par un seul caractère espace blanc (espace, tabulation, retour à la ligne, etc.), suivi par un caractère de mot (Chiffre ou lettre tel que défini dans XML 1.0) |
Espanñola |
Española |
\p{Lu} |
tout caractère majuscule, la valeur de \p{} (par
exemple "Lu") est défini par Unicode |
\p{IsGreek} |
tout caractère grec, la forme 'Is ' peut être appliquée
à tout nom (par exemple "Greek") tel que défini par Unicode |
\P{IsGreek} |
tout caractère non grec, la forme 'Is ' peut être
appliqué à tout nom (par exemple "Greek") tel que défini par Unicode |
a*x |
x , ax , aax ,
aaax .... |
a?x |
ax , x |
a+x |
ax , aax , aaax .... |
(a|b)+x |
ax, bx, aax, abx, bax, bbx, aaax, aabx, abax, abbx, baax,
babx, bbax, bbbx, aaaax .... |
[abcde]x |
ax, bx, cx, dx, ex |
[a-e]x |
ax, bx, cx, dx, ex |
[-ae]x |
-x, ax, ex |
[ae-]x |
ax, ex, -x |
[^0-9]x |
tout caractère autre qu'un chiffre suivi du caractère x |
\Dx |
tout caractère autre qu'un chiffre suivi du caractère x |
.x |
tout caractère suivi du caractère x |
.*abc.* |
1x2abc, abc1x2, z3456abchooray .... |
ab{2}x |
abbx |
ab{2,4}x |
abbx, abbbx, abbbbx |
ab{2,}x |
abbx, abbbx, abbbbx .... |
(ab){2}x |
ababx |
Index des éléments de XML Schema. Chaque nom d'élément est lié à une description XML formelle soit dans le tome "Structures" soit dans le tome "Types de données" de la spécification XML Schema. Les noms des éléments sont suivis d'un plusieurs liens vers les exemples (identifiés par les numéros de chapitre où ils se trouvent) de cette introduction.
all
:
2.7annotation
:
2.6any
:
5.5anyAttribute
:
5.5appInfo
:
2.6attribute
:
2.2attributeGroup
:
2.8choice
:
2.7complexContent
:
2.5.3complexType
:
2.2documentation
:
2.6element
:
2.2enumeration
:
2.3extension
:
2.5.1, 4.2field
:
5.1group
:
2.7import
:
5.4include
:
4.1key
:
5.2keyref
:
5.2length
:
2.3.1list
:
2.3.1maxInclusive
:
2.3maxLength
:
2.3.1minInclusive
:
2.3minLength
:
2.3.1pattern
:
2.3redefine
:
4.5restriction
:
2.3, 4.4schema
:
2.1selector
:
5.1sequence
:
2.7simpleContent
:
2.5.1simpleType
:
2.3union
:
2.3.2unique
:
5.1Index des attributs de XML Schema. Chaque nom d'attribut est suivi par une ou plusieurs paires de références. Chacune est composée d'un lien vers un des exemples de ce tome et d'un lien vers la description XML formelle se trouvant soit dans le tome "Structures" soit le tome "Types de données"(Datatypes) de la spécification XML Schema.
abstrait
: element declaration [
Structures], type complexe définition [
Structures]attributeFormDefault
:
schema
element [
Structures]base
: type
simple définition [
Datatypes], type complexe définition [
Structures]block
: type
complexe définition [
Structures],blockDefault
: schema
element [
Structures]default
: attribute declaration [
Structures],default
: element declaration [
Structures],elementFormDefault
:
schema
element [
Structures]final
: type
complexe définition [
Structures]finalDefault
: schema
element [
Structures]fixed
: attribute declaration [
Structures],fixed
: element declaration [
Structures]fixed
: type simple définition [
Datatypes]form
: element declaration [
Structures], attribute declaration [
Structures]itemType
: list type définition [
Datatypes]memberTypes
: union type définition [
Datatypes]maxOccurs
: element declaration [
Structures]minOccurs
: element declaration [
Structures]mixed
: type complexe
définition [
Structures]name
: element
declaration [
Structures], attribute declaration [
Structures], type complexe définition [
Structures], type simple définition [
Datatypes]espace de noms
: any
element [
Structures], include
element [
Structures]noNamespaceSchemaLocation
:
instance
element [
Structures]xsi:nil
: instance
element [
Structures]nillable
: element declaration [
Structures]processContents
:
any
element [
Structures], anyAttribute
element
[
Structures]ref
: element
declaration [
Structures]schemaLocation
: include specification [
Structures], redefine specification [
Structures], import specification [
Structures]xsi:schemaLocation
:
instance attribute [
Structures]substitutionGroup
: element declaration [
Structures]targetNamespace
:
schema
element [
Structures]type
: element
declaration [
Structures], attribute declaration [
Structures]xsi:type
: instance
element [
Structures]use
: attribute declaration [
Structures]xpath
: selector
& field
éléments
[
Structures]Les types simples de XML Schema sont décrits dans le tableau 2.